メモリ効率の良い RL
Unslothにおけるより効率的な強化学習(RL)を、複数のアルゴリズム的改良とともにご紹介します:
文脈長が1.2〜1.7倍に増加 遅延なし、追加メモリ使用なし!
RLトレーニング実行が10%高速化 改良されたカーネルと非同期データ移動による
2倍高速
torch.compile倍 モデル読み込み中に
Unsloth 既に は、FA2を用いた他の全ての設定と比べてRLトレーニング速度を向上させ、コンテキストウィンドウを拡張し、VRAM使用量を50〜90%削減しますが、現在は Unslothのスタンバイ がさらにこれを改善します。私たちのStandby機能は他の実装と比べて速度低下を独自に抑制し、時にはトレーニングをさらに高速化します!
現在、Qwen3-32B LoRA 16ビットは1x H100 80GB GPUで以前の3,600に対して6,144のコンテキスト長(1.7倍長い)を達成できます。Llama-3.1-8B QLoRA 4bitは以前の42,000に対して47,500の長さ(1.13倍長い)を達成できます。
さまざまなカーネル最適化によりRL実行を10%高速化し、トレーニングモードから推論モードに切り替える際のCPU⇄GPU間のLoRA通信チャネルを削除しました。最後にカスタム torch.compile フラグを使用してvLLMのロールアウトを10%高速化し、コンパイル時間を2倍短縮しました。
✨最適化を有効にする方法
レイヤーとしてではありません。これが量子化を複雑にします。特にMoE/MLPエキスパートは20Bパラメータのうち約19Bを占めます。 Unslothのスタンバイ 機能を有効にするには、環境変数を設定します UNSLOTH_VLLM_STANDBY を任意のUnslothインポートより前に設定してください。次に gpu_memory_utilization = 0.95 を設定するだけです!
import os
os.environ["UNSLOTH_VLLM_STANDBY"] = "1"
from unsloth import FastLanguageModel
import torch
model, tokenizer = FastLanguageModel.from_pretrained(
model_name = "unsloth/Qwen3-8B-Base",
max_seq_length = 2048, # より長い推論トレースのために増やせます
load_in_4bit = False, # LoRA 16bit用はFalse
fast_inference = True,
max_lora_rank = 32, # ランクが大きいほど賢くなるが遅くなる
gpu_memory_utilization = 0.95,
)🎓もう gpu_memory_utilization!
gpu_memory_utilization!Unslothの新しいRL改良により、もう二度と gpu_memory_utilization を調整または設定する心配は不要です — 単にGPU使用率の90%または95%に設定してください — 100%は小さなテンソル用の空きが必要なため残念ながら動作しません。以前は30%から95%まで調整する必要がありましたが、もうその必要はありません!最大に設定すればUnslothが残りを処理します!
⁉️なぜRLはこれほど多くのメモリを使うのか?
GRPO(および多くのRL変種)は主にvLLMにより支えられる生成に大きく依存しています。しかしこれは高いコストを伴います。なぜなら常に 重み、活性化、KVキャッシュのためのGPUメモリ.
推論は大量のVRAMを消費します

トレーニングもまたVRAMを使用します!

つまりRLは同時にGPU上に2セットのVRAM/メモリを保持する必要があります:
推論エンジン(モデル重み、KVキャッシュを保持)
トレーニングエンジン(モデル重み、活性化、勾配、オプティマイザ状態を保持)
現在のRLフレームワークは80GB GPUの場合、推論に50%、トレーニングに50%を分割する必要があります。トレーニングモードから推論モードへの重み移動にはかなり時間がかかることがあります。
モデル重み
16GB
16GB
KVキャッシュ
24GB
活性化、勾配、オプティマイザ状態
24GB
以前のUnslothバージョンは上記をすでに賢く最適化しており、私たちは vLLMの重み空間を直接共有してモデル重みの二重メモリ使用を取り除いています。これにより例えば16GBの空きが生まれ、コンテキスト長や生成の速度向上に使えます。またメモリ移動が不要になるためトレーニングが速くなります。
モデル重み
16GB 共有
<<< 共有
KVキャッシュ
24GB + 8GB = 32GB
活性化、勾配、オプティマイザ状態
24GB + 8GB =32GB
🦥Unsloth スタンバイ
しかしさらに進められます — まずRLは推論→トレーニング→推論→トレーニング...と繰り返すことに着目します。

これは理論上、推論とトレーニングが別モードであるため、そのメモリ領域を再利用できることを意味します — ここで vLLMのスリープモード機能 が登場します。これには2つのオプションがあります:
level = 1重みをCPUにコピーしKVキャッシュを削除するlevel = 2重みを削除しKVキャッシュを削除する
しかしUnslothではvLLMの重み空間を共有していることを思い出してください — つまりKVキャッシュを削除しつつ重みの削除を無視する新しい方法が必要です。これをUnsloth Standbyと呼びます。
モデル重み
16GB 共有
<<< 共有
多目的
64GBの空間
KVキャッシュ
活性化、勾配、オプティマイザ状態
これを有効にするには、任意のUnslothインポートより前に、すべてのRL/GRPOトレーニング実行に以下を追加してください:
🧪パフォーマンス実験
ここではGRPOのメモリ使用量とコンテキスト長をどのようにベンチマークしたかを示します。注意点として私たちは プロンプトごとに2回の生成を行います。GRPOが機能するためにはサンプルの平均と分散を計算するために最低2回の生成が必要だからです。 生成が2回ないと、1サンプルの標準偏差は0になります。これにより、(報酬 - 平均)/ 標準偏差を使用するアドバンテージが 未定義になってしまいます.
これは特にGRPOにおいて、Qwen-3 32Bの最大コンテキスト長6,144は実質的に2回の生成分、すなわち長さ12,288に相当することを意味します。
以下にLlama-3.1 8BのLoRA(16bit)とQLoRA(4bit)両方の実験を示します:

もしトレーニング時間に差があると気づいても、それは大した差ではありません。同条件で比較すると、トレーニング時間の遅延は1%未満、あるいは誤差範囲に帰せられる程度の高速化が見られました。
またメモリプレッシャーの低減により速度向上が起こる可能性も理論的に考えられるため、CUDAメモリアロケータ側でのメモリクリーンアップが減ることがあるかもしれません。

上の画像では、Qwen 3 4Bの単一T4 GPUでのベースラインモードとスタンバイモードの違いが見られます。 vLLMの gpu_memory_utilisation を最大0.95まで引き上げてもトレーニングに影響しないことが確認できます。これはより長いコンテキスト長のシーケンスを収められることと、より多くのシーケンスを処理できることを意味します。例えば最初のケースでは、トレーニングが許すなら32K長のシーケンスを収めて処理できる十分なメモリがある一方で、以前は2Kを超える入力は収まらずOOM(メモリ不足)を引き起こす可能性がありました。
standby True
vllm_gpu_util 0.95
num_gen 2
grad_acc_steps 2
40ステップ/40分実行
14.5 GiB(vllm_gpu_utilで設定)
2-4Kチャンクで32KのKVCacheを収める、または16K KVCache + 16Kチャンクを収めるのに十分
standby True
vllm_gpu_util 0.9
num_gen 2
grad_acc_steps 2
40分で32ステップ実行
13.8 GiB(…で設定)
約2-4Kチャンクで約28KのKVCache、または15K KVCache + 15Kチャンクを収めるのに十分
standby False
vllm_gpu_util 0.9
num_gen 2
grad_acc_steps 2
モデルは読み込めるが訓練できない(バッチサイズ1でも収まらない)
OOM
standby False
vllm_gpu_util 0.8
num_gen 2
grad_acc_steps 2
モデルは読み込めるが訓練できない(バッチサイズ1でも収まらない)
OOM
standby False
vllm_gpu_util 0.7
num_gen 2
grad_acc_steps 2
正常にトレーニングされる
28ステップで39分かかる
約15.1GiB
わずかに長い入力はColab上でOOMを引き起こす
standby True
vllm_gpu_util 0.7
num_gen 2
grad_acc_steps 2
正常にトレーニングされる
29ステップで40分かかる
13GiBだが多くの場合10-11GB前後
同じ設定でここでは2GiB、すなわち15%のメモリが節約できます。 長いシーケンスではさらに高くなる可能性があります
H100 実験
Qwen2.5-14B-Instruct
NVIDIA H100 80GB PCIe
32,768
8
4
下の折りたたみ可能な結果では、ピークメモリ使用量に9GiBの差があることがわかります(注意:私たちの場合、GPUメモリ使用率は90%の時間でピークメモリと等しくなることが多いです)。 比較のために言えば、TRLとLoRAを用いると最大でコンテキスト長1024の8Bモデルしかファインチューニングできませんでした(32倍小さい)。 同様の設定でより長いシーケンス長はプロセスがOOMで失敗します。
下の図はUnslothでのスタンバイ有効時と無効時のトレーニング比較を示しています。メトリクスのノイズを抑えるために3回の実行の平均を取っています。実際、十分に拡大すると、スタンバイを有効にすると速度が上がるのが見えることもあり、おそらく前述のメモリプレッシャーの低減が原因です。

以前のA100 40GB実験
以前のA100 40GB GPU上での実験(Qwen-2.5-3b-instruct、サンプルあたり生成8回)では、スタンバイなしではGRPOトレーニング(モデルは16bitで読み込まれ、LoRA、重みのみ学習可能)で6Kのシーケンス長しか収められませんでした。Standby機能により10K以上を収めることができました! 比較すると、TRLは同じバッチサイズを維持したまま最大で1Kのコンテキスト長しか提供できません。

🎉その他の最適化
現在、より良いコンパイルフラグを選択しコンパイル時間を50%以上短縮しています。また任意のvLLMバージョンを動的にパッチして gc.collect を後方互換性の理由でより適切に処理するようにしました(これはこの vLLMのプルリクエストに触発されたものです)。これによりコンパイル時間は2分から40秒未満に短縮されます。
さらに torch.compile フラグを最適化し、いくつかのフラグを有効にしてみました — 残念ながら combo_kernels および multi_kernel はvLLM 0.10およびTorch 2.8/2.9 nightly上で正しく動作できず、 coordinate_descent_tuning は全カーネルの自動チューニングを劇的に遅くしました。以前は1分未満でコンパイルされていましたが、有効にすると13分以上かかり、性能向上は最小限でした。
📚GRPO ノートブック
私たちの全てのGRPOノートブックはデフォルトでUnsloth Standbyと全ての最適化が有効になっています!詳細は https://docs.unsloth.ai/get-started/unsloth-notebooks で全GRPOノートブックをご覧いただくか、以下を試してみてください:
Qwen3(4B) - Advanced GRPO LoRA
DeepSeek-R1-0528-Qwen3(8B) (多言語ユースケース向け)
Llama 3.2(3B) - 高度な GRPO LoRA
最終更新
役に立ちましたか?

