16のオープンソースRLライブラリで見えたLLM非同期訓練の設計パターン
HuggingFaceのブログで、現在存在する16のオープンソースRL(強化学習)訓練ライブラリの比較分析が公開された。verl、PRIME-RL、AReaL、SkyRLなどをカバーし、設計上の選択を7つの軸に整理している。
同期型の根本的なボトルネック
現在のTRL(Transformers Reinforcement Learning)を使ったGRPO訓練は同期的に動く。プロンプトをサンプルして、生成して、報酬を計算して、勾配を更新して、推論サーバーに重みを送る、という流れがステップごとにブロックする。
問題は生成にかかる時間だ。GRPO標準の設定(G=8完成×64プロンプト=512ロールアウト)で、出力長別の所要時間はこうなる。
| 出力長 | 総トークン数 | 7B/H100 | 32B/H100 |
|---|---|---|---|
| 2K | 約100万 | 3分 | 14分 |
| 8K | 約400万 | 11分 | 56分 |
| 32K | 約1600万 | 45分 | 3.7時間 |
推論は止まり、訓練GPUは待ち、また推論する。この繰り返しで実効GPU利用率は60%程度に落ちる。CoTで長い推論トレースを出力させるほど悪化する。
sequenceDiagram
participant P as プロンプトサンプリング
participant G as 生成 (数分〜3.7時間)
participant R as 報酬計算
participant T as 訓練ステップ
participant S as 重み同期
P->>G: 64プロンプト
note over G: GPU稼働
G->>R: 512ロールアウト
note over T: GPU待機
R->>T: 報酬付きサンプル
T->>S: 更新済み重み
note over G: GPU待機
S-->>G: 次のステップへ
非同期設計はこの生成と訓練を分離して並列実行させる。推論プールが生成し続ける間、訓練プールがバッファから取り出して更新を続ける。GPU利用率は95%以上になる。
7つの設計軸
16ライブラリの差異を整理すると7つの軸に収まる。
1. オーケストレーションの基盤
16ライブラリのうち8つがRayを使う。残りはasyncio+マルチプロセス、Redisキューベースのpub/sub、HTTPマイクロサービスに分かれる。
Rayが多数派になっているのは理由がある。推論プールと訓練プールはGPU要件が異なるヘテロジーニアスな構成で、そのリソース管理と障害復旧をRayが自動化する。共有メモリオブジェクトストアによるゼロコピー転送も大規模環境では効いてくる。
一方でNative Pythonを選ぶライブラリも増えている。PipelineRL(ServiceNow)やART(OpenPipe)はasyncioとマルチプロセスで実装されており、Ray依存なしでシンプルに動く。単一〜少数ノード環境ではこちらの方が扱いやすい。
2. ロールアウトバッファの深さ
生成済みサンプルをどう溜めるかで設計が変わる。
| バッファタイプ | 深さ | 採用例 |
|---|---|---|
| バッファなし(同期) | 0 | TRL現行 |
| ダブルバッファ | 1 | verifiers-rl, SLIME |
| 有界キュー | 2〜K | SkyRL, verl, NeMo-RL |
| 無制限ストリーム | ∞ | PipelineRL, Atropos |
バッファを深くするほどスループットは上がるが、バッファ内のサンプルが古くなる(staleness)問題が大きくなる。
3. 重み同期プロトコル
訓練後の重みを推論サーバーに転送する方法は主に4種類で、速度に大きな差がある。
NCCL Broadcast(最も一般的):per-parameterのbroadcastで32Bモデルだと約500ms。単純だが遅い。
Bucketed NCCL(verl):パラメータを1GBバケットにまとめてまとめて送る。同じ32Bモデルで約20ms。25倍の改善。
CUDA IPC(NeMo-RL, MILES):同一ノード上での推論と訓練が前提。ゼロコピーで超低レイテンシ。
LoRA adapter-only sync(AReaL, OAT, SkyRL):これが最も効果的。ベース重みは推論サーバーにそのままで、学習したLoRAアダプターだけを転送する。
Full weight sync(32Bモデル):
32B params × 2 bytes (bf16) = 64GB
NCCL転送: 約500ms
LoRA adapter-only sync(rank-32):
約50MB
NCCL転送: 約1ms
差: 500倍の削減
この1000倍に近い削減は、重み同期にまつわる複雑さの大部分を解消する。
4. Staleness管理
バッファ内サンプルが古くなった時どう扱うかについて、3つの直交する戦略がある。
Version rejection:サンプルに生成時のポリシーバージョンを記録し、現在のバージョンとの差が閾値を超えたら破棄する。NeMo-RL(max_trajectory_age_steps)、PipelineRLなどが採用。
Depth bounding:バッファサイズを制限して自動的にstaleness上限を設ける。SkyRL(max_staleness_steps)、Atroposなどが採用。
Importance sampling(IS)補正:古いポリシーで生成したサンプルに重み補正をかけて訓練に使う。verl、MILES、ROLLなどが採用。PPOスタイルのclipped IS ratioが一般的。
本番環境で最も堅牢なのはハイブリッド構成で、PRIME-RL(PrimeIntellect)がversion rejection + depth bounding + ISの3つを組み合わせた実装を持つ。
5. 部分ロールアウト処理
重み更新時に生成途中のロールアウトをどう扱うかも重要な設計決定。
- PipelineRL:フォワードパス間で重みを交換。生成は中断せず新しい重みで続行(最も細かい粒度)
- verl:KVキャッシュのプレフィックスを保存して、重み更新後に再開
- SkyRL/SLIME:進行中のリクエストを中止してプロンプトから再投入
- NeMo-RL/ROLL:訓練ステップ単位でブロック(最も粗い粒度)
6. LoRAサポート
16ライブラリのほぼすべてがLoRAに対応しているが、adapter-only syncまで実装しているかどうかで差がある。SLIMEとTorchForgeはLoRA自体未対応。
MoE(Mixture of Experts)モデルのLoRAは新しい問題を抱えている。Dense LoRAなら注意層に約20個のアダプターだが、64 expertsのMoEにLoRAをかけると200個以上のアダプターが expert parallelism で分散する。現状でMoE LoRAの明確な実装を持つのはARTのみ。
7. 分散訓練バックエンドと並列化
| ライブラリ | バックエンド | TP+PP+EP対応 | MoE |
|---|---|---|---|
| verl | FSDP+Megatron | ✅ | ✅ |
| NeMo-RL | FSDP2+Megatron | ✅ | ✅ |
| SkyRL | FSDP+Megatron | ✅ | ✅ |
| PRIME-RL | FSDP2 | ✅(PP未対応) | ✅ |
| AReaL | FSDP2+Megatron | ✅ | ✅ |
| PipelineRL | DeepSpeed | ❌ | ❌ |
| open-instruct | DeepSpeed | ❌ | ❌ |
DeepSpeed ZeRO-3はExpert Parallelismをサポートしていないため、MoEモデルでは全エキスパートをAllGatherしてしまいスパース性のメリットが消える。MoEモデルを大規模訓練するならMegatronパスが必須になる。
16ライブラリの主要指標一覧
ライブラリ | 組織 | Stars | オーケストレーション | LoRA | MoE
verl | ByteDance | 19.7K | Ray | ✅ | ✅
ART | OpenPipe | 9.0K | asyncio+mp | ✅ | ✅
SLIME | THUDM | 4.6K | Ray | ❌ | ✅
AReaL | inclusionAI | 4.3K | asyncio/Ray | ✅ | ✅
verifiers-rl | PrimeIntellect | 3.9K | asyncio+threading| ✅ | ❌
open-instruct | AI2 | 3.6K | Ray | ❌ | ❌
ROLL | Alibaba | 2.9K | Ray | ✅ | ✅
Tunix | Google | 2.2K | asyncio+JAX | ✅ | ❌
SkyRL | NovaSky-AI | 1.7K | Ray | ✅ | ✅
NeMo-RL | NVIDIA | 1.4K | Ray | ✅ | ✅
PRIME-RL | PrimeIntellect | 1.1K | asyncio+FS/ZMQ | ✅ | ✅
MILES | radixark | 1.0K | Ray | ✅ | ✅
Atropos | NousResearch | 0.9K | HTTP | ✅ | ❌
TorchForge | Meta | 0.6K | Monarch(PyTorch) | ❌ | ❌
OAT | SAIL-SG | 0.6K | Ray | ✅ | ❌
PipelineRL | ServiceNow | 0.4K | asyncio+Redis | ✅ | ❌
DeepSeek-V3.2が示す未解決問題
16ライブラリ全てに影響する未解決の問題がある。DeepSeek-V3.2の事例がそれを明らかにした。
Keep Routing問題:推論時(vLLM)と訓練時(Megatron)でexpert routingの計算が微妙に異なり、浮動小数点の丸め差で異なるエキスパートが選ばれる場合がある。解決には推論時のrouting pathsをサンプルに記録し、訓練時に強制的に再適用する必要がある。
Keep Sampling Mask問題:top-pサンプリングで一部の語彙をマスクして生成した場合、訓練時に同じマスクを適用しないとImportance Samplingのratioが未定義になる。こちらも推論時のマスクを保存して訓練時に再適用する必要がある。
どちらも現時点で対応しているライブラリはゼロ。次世代の訓練フレームワークが解決すべき課題として残っている。
用途別の選択指針
最大スループット(100M tokens/day以上)が必要なら verl(ByteDance)。Megatron + EP完全対応で、bucketed NCCLによる20ms重み同期が実現できる。
シンプルさを優先するなら PipelineRL か ART。Rayなしのnative Python実装で、少数GPU環境でも扱いやすい。
staleness管理を厳密にやりたいなら PRIME-RL(PrimeIntellect)。Version rejection + depth bounding + ISの3層ハイブリッドで、process rewardsにも対応済み。
MoEモデル訓練が必要なら verl、NeMo-RL(NVIDIA公式)、SLIME(THUDMはDeepSeekに近い組織)。
任意の推論サーバーに対応させたいなら Atropos(NousResearch)。FastAPIベースのHTTPマイクロサービスでvLLM/SGLang/OpenAI API互換の任意サーバーを使える。その分レイテンシは高くなる。