vLLMによるNVIDIA B300 GPU上でのGLM-5.2のサービング

vLLMによるNVIDIA B300 GPU上でのGLM-5.2のサービング

vLLMは、分散型Prefill/Decode (P/D) トポロジーを使用し、24枚のNVIDIA B300 GPU(8-GPUサーバー3台)上でGLM-5.2-NVFP4のデプロイに成功しました。ピークスループットではなく、サービスレベル合意(SLA)の遵守を最適化することで、チームは平均Time Per Output Token (TPOT) を約40 msから17 msに短縮し、コンテキスト長16K〜256Kトークンの範囲で、平均TTFT ≤ 2.5 sおよび平均TPOT ≤ 20 msというプロダクション目標を達成しました。

ピークスループットよりもSLA遵守を優先

コロケーション(同居)サービングでは、prefillチャンクがdecodeバッチとインターリーブ(混在)することがあり、長いプロンプトが既存のリクエストのトークン間レイテンシを増大させる原因となります。vLLMはP/D disaggregation(分離)を利用してprefillの作業をdecodeのクリティカルパスから排除し、TPOTがdecodeバッチの構成のみによって決定されるようにしています。

今回のデプロイにおけるプロダクション要件は以下の通りです:

  • コンテキスト長: 16K–256Kトークン。
  • 平均TTFT (Time to First Token): ≤ 2.5 s。
  • 平均TPOT (Time Per Output Token): ≤ 20 ms (約50 tokens/s)。
  • スループット: 上記2つのレイテンシ制約が満たされた後に最大化。

GLM-5.2は、40Bのアクティブパラメータを持つ744BパラメータのMoEモデルであり、DSA sparse attentionとMTP speculative decodingを利用しています。

Decodeパフォーマンスの最適化

初期設定では、16Kトークンの入力に対して平均TPOTは約40 msでした。SLAの制限内に収めるために、以下の最適化が実施されました:

Mixed BatchesのためのSpeculative Padding

プロファイリングにより、リクエストがPrefillノードからDecodeノードに転送される際、最初のDecodeステップでは1トークンしか必要としない一方で、Multi-Token Prediction (MTP) を使用している既存のリクエストは1 + Nトークンを必要とすることが判明しました。この不一致がmixed batch(混合バッチ)を生み出し、システムが高速なCUDA Graphパスから、コストのかかるpiecewiseまたはeager実行へのフォールバックを強制する原因となっていました。

これを解決するために、vLLMはDecode側にspeculative paddingを実装し、新しいリクエストの最初のステップにダミーのトークンを追加して1 + Nの形状に合わせました。この最適化(PR #45237でマージ)により、平均TPOTは40 msから22 msに短縮されました。

Model Runner V2 (MRV2)

Model Runner V2 (VLLM_USE_V2_MODEL_RUNNER=1) を有効にすることで、TPOTが11%削減されました。主な改善点は以下の通りです:

  • Warmup Kernels: コールドスタート時のレイテンシスパイクを防ぐため、GLM-5.2 DSA indexer prefill-metadata kernelがスタートアップのウォームアップに追加されました (PR #47285)。
  • Local Argmax Reduction: マルチGPU MTPにおいてローカルargmax reductionが採用され (PR #46448)、TP通信ボリュームが全語彙のlogitsから約2 × TPサイズに削減されました。
  • Dynamic Speculative Lengths: フルCUDA Graphsが動的なspeculative lengthsをサポートし (PR #45953)、eagerへのフォールバックが削減されました。

通信およびGraph設定

  • All-to-All Backend: デフォルトのEP backendを flashinfer_nvlink_two_sided backendに置き換えることで、TPOTが4%削減されました。

  • CUDA Graph Mode: Decodeインスタンスは、起動時のコンパイル時間を短縮しつつ完全なグラフカバレッジを提供する --max-num-batched-tokens 1024 を伴う FULL_DECODE_ONLY モードを使用しています。

  • MTP設定: Decode側は実行コストを分散するために num_speculative_tokens=3 を使用し、Prefill側は高速なKV cacheハンドオフを優先するために num_speculative_tokens=1 を使用しています。

Prefillの並列性とキャパシティのトレードオフ

Prefillの並列戦略を評価する際、チームはTGS (throughput per GPU) を比較しました。TP1 DP4 EPはGPUあたりの絶対的な最高効率の設定ではありませんでしたが(TP1 DP2 EPの方が8%効率的)、GLM-5.2の1Mトークンのコンテキスト能力に必要なKV-cache容量を確保するためにTP1 DP4 EPが選択されました。

MTP受理率の安定化

高コンカレンシー(高並列)下でもspeculative decodingが効果的であり続けるよう、vLLMはIndexerCacheを実装しました (PR #44420)。このメカニズムは、DSA indexerによって生成されたTop-K sparse indicesを再利用し、システムがMTPのドラフトステップごとにインデクサーを再実行するのを防ぎます。

その他の安定化修正には以下が含まれます:

  • Indexer Initialization: Top-Kレイヤーをスキップする際の正規化ループと初期化の改善 (PR #45895)。
  • Shared Index Buffer: バッチリクエスト用にレイアウトを最適化し、最終クエリトークンのインデックスのみを保持するように変更 (PR #47238)。
  • Post-Final-Norm Hidden State: MTPループにおけるpost-final-norm hidden stateの再利用を保証 (PR #47448)。

AIME 2025 (86.67)、GPQA (92.89)、およびLongBench V2 (64.01) での精度検証により、これらの最適化が出力品質を低下させないことが確認されました。

プロダクションの観測可能性と安定性

分散型P/Dデプロイメントのモニタリングには、2つのリソースプールにわたるメトリクスの追跡が必要です。主なメトリクスには、プールごとのTTFT/TPOTパーセンタイル、MTP受理率、およびKV転送レイテンシが含まれます。

長期安定性テスト中に、チームはvLLMプロセスのRSSが数十時間にわたって線形に増加するホストメモリリークを発見しました。根本的な原因は SingleTypeKVCacheManager.new_block_ids (PR #35219) における不整合なゲーティングメカニズムであり、Mamba以外のモデルに対してブロック割り当てを記録しながら、それらを解放(drain)していませんでした。これは、すべてのスケジューリングステップで take_new_block_ids() を無条件に呼び出すことで修正されました。

デプロイ手順

ハードウェアとトポロジー

  • ハードウェア: 3 × 8 B300 GPU (合計24枚)。
  • モデル: GLM-5.2-NVFP4。
  • トポロジー: 4 Prefillノード (TP1 DP4 EP, 16 GPU) および 1 Decodeノード (TP1 DP8 EP, 8 GPU)。
  • KV Transfer: NIXL。

設定コマンド

Prefill Node:

export VLLM_USE_V2_MODEL_RUNNER=1
vllm serve /mnt/model/glm/GLM-5.2-NVFP4 --trust-remote-code --kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_producer"}' --chat-template-content-format=string -ep -tp 1 -dp 4 --tool-call-parser glm47 --enable-auto-tool-choice --reasoning-parser glm45 --gpu-memory-utilization 0.92 --enable-prompt-tokens-details --speculative-config='{"method":"mtp","num_speculative_tokens":1}' --shutdown-timeout 300 --fingerprint-mode=none

Decode Node:

export VLLM_USE_V2_MODEL_RUNNER=1
vllm serve /mnt/model/glm/GLM-5.2-NVFP4 --trust-remote-code --chat-template-content-format=string --kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_consumer"}' --compilation-config '{"cudagraph_mode":"FULL_DECODE_ONLY"}' --max-num-batched-tokens 1024 -ep -tp 1 -dp 8 --tool-call-parser glm47 --enable-auto-tool-choice --reasoning-parser glm45 --gpu-memory-utilization 0.90 --enable-prompt-tokens-details --all2all-backend=flashinfer_nvlink_two_sided --speculative-config='{"method":"mtp","num_speculative_tokens":3}' --shutdown-timeout 300 --fingerprint-mode=none

Sources