TL;DR
SGLangがEncoder-Prefill-Decode (EPD)デカップリングアーキテクチャを発表し、視覚言語モデル(VLMs)における視覚エンコーディングと言語処理を分離し、以下の利点を実現:
- 視覚エンコーディング容量の独立拡張:エンコーダーサーバーは水平スケーリングが可能で、言語モデルのデプロイメントに影響を与えず、視覚集約型負荷のリソース利用を最適化。
- 既存のPDデカップリングとの互換性:EPDはPrefill-Decodeデカップリングと組み合わせて、完全な3層アーキテクチャを形成。
- 柔軟な転送バックエンド:ZMQ、Mooncakeなど複数の転送メカニズムをサポートし、異なるデプロイメントシナリオに対応。
- 視覚埋め込みキャッシュ:よく使用される画像はエンコーダーサーバーでキャッシュでき、重複するViT計算を回避し、ネットワーク転送のオーバーヘッドを削減。
EPDは画像密集シナリオ(複数画像入力など)で効果が顕著で、視覚エンコーディングが主なボトルネック。EPDにより、負荷下でリクエストのTTFTが大幅に削減され、同一配置ソリューションと比較して遅延が約6〜8倍低下(1 QPSの場合)。一方、画像疎シナリオでは、追加のネットワーク遅延によりTTFTが高くなる可能性がある。
はじめに
Qwen2.5-VLやLlama-Visionなどの視覚言語モデル(VLMs)は視覚理解と言語生成を融合させているが、独特のスケーリング課題に直面している:
- 異種計算要求:視覚エンコーディング(CNN/ViT)と言語デコーディング(Transformer)の計算パターンが異なる。
- リソース使用の不均衡:視覚処理は計算集約的だが、prefillフェーズでのみ必要。
- 柔軟性の不足:従来のモノリシックデプロイメントでは視覚と言語コンポーネントを独立してスケーリングできない。
- リクエスト内並列性:同じリクエスト内の異なる画像は独立してエンコード可能。
- テンソル並列スケーリングの不良:視覚エンコーダーのパラメータは言語コンポーネントよりはるかに少なく、テンソル並列は非効率で不要。
SGLangの既存のPrefill-Decode(PD)デカップリングはすでにprefillとdecodeフェーズを分離している。EPDはさらに視覚エンコーディングと言語prefillを分離し、3層アーキテクチャを形成。
ViTスケーリング問題:なぜテンソル並列が常に有効ではないのか
直感に反する発見
EPDの重要な洞察は、Vision Transformers(ViT)がテンソル並列度(TP)の増加から恩恵を受けないことで、TPが高いほど遅くなる可能性すらある:
H20上でのQwen2.5-VL-72Bベンチマーク(リクエストあたり4画像):
| TP | ViT平均時間 |
|---|---|
| 2 | 492.13ms |
| 4 | 465.80ms |
| 8 | 523.80ms |
理由:
- 通信オーバーヘッドが実行時間を支配。
- 視覚モデルの重みパラメータは通常小さい。
EPDはTPを増やすのではなく、エンコーダーの水平スケーリングによってこの問題を回避。
アーキテクチャ概要
EPDアーキテクチャのリクエストフロー:
- クライアントリクエスト:マルチモーダルリクエストがprefillサーバーに到達(ロードバランサー経由または直接接続)。
- 画像配信:prefillサーバーが画像入力を識別し、1つ以上のエンコーダーサーバーに配信。画像は負荷分散のため分割可能。
- 視覚エンコーディング:エンコーダーサーバーがViTで画像を処理し、視覚埋め込みと画像グリッドメタデータを生成。有効な場合は結果をキャッシュ。
- 埋め込み転送:視覚埋め込みは設定された転送バックエンド(ZMQ、Mooncakeなど)経由でprefillサーバーに返送。
- LLM計算:prefillサーバーが視覚埋め込みとテキストトークンを結合し、事前計算テンソルを含むmm_inputsを形成。LLMがPrefillとDecodeを実行。PDが有効な場合は既存の転送ロジックを再利用;そうでない場合はローカルでデコード。
主要コンポーネント

エンコーダーサーバー (--encoder-only)
- 視覚のみ(言語重みなし);前処理 + ViTフォワードで視覚埋め込みを生成
- プレフィックスマルチモーダルキャッシュをサポート
- 負荷分散と複数画像並列分割推論のための水平スケーリング
Prefillサーバー (--language-only)
- 言語モデルのみ
- エンコーダー埋め込みを受信
- PD有効:DecodeにKVを送信;そうでない場合はローカルデコード
Decodeサーバー
- 標準的なdecode専用インスタンス
- prefillからKVキャッシュを受信
実装詳細
画像配信戦略
単一モデルを分割するテンソル並列とは異なり、EPDはデータ並列を使用:複数の独立したエンコーダーインスタンスを実行し、画像を配信。
例(7画像、3エンコーダー):
Request with 7 images: [img0, img1, img2, img3, img4, img5, img6]
3 encoders available
Distribution (after shuffle):
├─ Encoder 0: [img0, img1, img2] (3 images)
├─ Encoder 1: [img3, img4] (2 images)
└─ Encoder 2: [img5, img6] (2 images)転送バックエンド
EPDは3つの視覚埋め込み転送バックエンドをサポート:
- zmq_to_scheduler (デフォルト):直接ZMQソケット通信、RDMA転送エンジン経由で埋め込みをスケジューラーに送信、非ブロッキング。
- zmq_to_tokenizer:埋め込みをtokenizer managerに送信、トークン化段階で処理。
- mooncake:マルチノードRDMA転送、共有メモリに埋め込みを登録、高帯域幅低遅延。
視覚埋め込みキャッシュ
エンコーダーはプレフィックスマルチモーダルキャッシュをサポートし、重複するViT計算を回避:
- 冗長な視覚エンコーディングを削除
- 繰り返し画像の遅延を削減
- 設定可能なキャッシュサイズ(デフォルト4GB、SGLANG_VLM_CACHE_SIZE_MB経由)
使用例
エンコーダーインスタンスの起動:
MODEL=Qwen/Qwen2.5-VL-7B-Instruct
PORT=30002
CUDA_VISIBLE_DEVICES=2 taskset -c $1 python -m sglang.launch_server \
--model-path $MODEL \
--encoder-only \
--enable-prefix-mm-cache \
--port $PORTprefillインスタンスの起動:
MODEL=Qwen/Qwen2.5-VL-7B-Instruct
PORT=30000
TP=1
MEM_FRACTION=0.5
CHUNK_SIZE=8192
SGLANG_VLM_CACHE_SIZE_MB=0 CUDA_VISIBLE_DEVICES=0 python -m sglang.launch_server \
--model-path $MODEL \
--disaggregation-mode prefill \
--disaggregation-transfer-backend nixl \
--tp $TP \
--mem-fraction-static $MEM_FRACTION \
--disable-radix-cache \
--chunked-prefill-size $CHUNK_SIZE \
--language-only \
--encoder-urls http://127.0.0.1:30002 http://127.0.0.1:30003 http://127.0.0.1:30004 http://127.0.0.1:30005 http://127.0.0.1:30006 http://127.0.0.1:30007 \
--port $PORTdecodeインスタンスの起動:
MODEL=Qwen/Qwen2.5-VL-7B-Instruct
PORT=30001
TP=1
CUDA_VISIBLE_DEVICES=1 python -m sglang.launch_server \
--model-path $MODEL \
--disaggregation-mode decode \
--disaggregation-transfer-backend nixl \
--tp $TP \
--port $PORTminlbの起動:
python -m sglang_router.launch_router \
--pd-disaggregation \
--mini-lb \
--prefill http://127.0.0.1:30000 \
--decode http://127.0.0.1:30001 \
--port 8000ベンチマーク
EPDは視覚集約型負荷(複数画像リクエスト)を対象とし、エンコーダーの水平スケーリングによってTTFTを向上。
ベンチマークスクリプト:
python -m sglang.bench_serving \
--random-image-count \
--model ${MODEL_PATH} \
--num-prompts 64 \
--dataset-name image \
--random-input-len 128 \
--random-output-len 256 \
--image-count 8 \
--image-resolution 1080p \
--host $HOST_IP \
--port $port \
--backend vllm-chat \
--request-rate $request_rate実験設定
環境:8× H20 96GB GPU
モデル:Qwen3-VL-235B-A22B-Instruct-FP8
データセット:ランダムマルチモーダルデータセット
- テキストトークン:128 / 256
- リクエストあたり画像:1-8枚(ランダム、平均 ~4枚)
- 画像解像度:1080p
- QPS範囲:0.2-1.0
デプロイメント設定:
- Colocate:1 PDインスタンス、tensor-parallel-size=4、4× H20使用
- 1E1P:1エンコーダー (TP=1) + 1 PD (TP=4)、5× H20使用
- 2E1P:2エンコーダー (各TP=1) + 1 PD (TP=4)、6× H20使用
テスト結果
平均TTFT (EPD vs colocate):

平均TPOT (EPD vs colocate):

リクエストスループット (EPD vs colocate):

主要な発見(vs. colocate):
- 負荷下でエンコーダー/prefillはTTFTをcolocateよりはるかに低く維持(1 QPSで≈6〜8倍低い)。
- TPOTはcolocateよりはるかに低い(≈8〜10倍低い)、遅延がよりコンパクト。
- 高QPSでスループットが約2倍(0.8〜1.0 QPSで≈2倍)。
- エンコーダーに専用GPUリソースを割り当てることで、TTFTの劇的な削減を実現。2E1Pは50%多くのGPU(6× vs 4×)を使用するが、より高いリソース利用率を達成。
© 2026 Winzheng.com 赢政天下 | 转载请注明来源并附原文链接