7月11日、AWSが「Disaggregated prefill and decode for LLM inference on SageMaker HyperPod」と題した記事を公開した。SageMaker HyperPod上でvLLMを使ったPrefill/Decode分離推論(DPD)を実装する手順について詳しく紹介されており、長文プロンプトによってストリーミング中のトークン生成が乱れるレイテンシスパイクを構造的に解消するアプローチとして注目される。
なぜPrefillとDecodeを分離するのか
LLM推論には性質の異なる2つのフェーズがある。
- Prefill:入力プロンプト全体を並列処理してKVキャッシュを生成する。演算律速(compute-bound)。
- Decode:1トークンずつ生成する。メモリ帯域律速(memory-bound)で、モデルの重みと肥大化するKVキャッシュへの高速アクセスが必要。
この2つを同じGPUで動かすと、長いプロンプトのPrefill処理が実行中の全Decodeリクエストをブロックする。4,096トークンを超えるような長文プロンプトが複数同時に来ると、per-tokenレイテンシのスパイクが発生するのはこの構造的な問題による。
Disaggregated Prefill and Decode(DPD)はこの干渉をなくすため、PrefillとDecodeをそれぞれ専用のGPUプールに分離し、Elastic Fabric Adapter(EFA)のRDMA(Remote Direct Memory Access)経由でKVキャッシュを転送する構成だ。
アーキテクチャの全体像
HyperPodのDPD実装は、vLLM Production StackのルーターとLMCache(KVキャッシュ転送レイヤー)を組み合わせた3コンポーネント構成だ。
インテリジェントルーター
制御プレーンとして機能する。各プロンプトをトークナイズし、設定可能なトークン数閾値(routingThreshold)に基づいてリクエストの振り分けを決定する。
- 閾値を超える長文プロンプト → Prefiller → Decoder の分離パス
- 閾値以下の短いプロンプト → Decoderへ直接転送(EFA越しのKV転送コストが割に合わないため)
ルーティング戦略として prefixaware、kvaware、session、roundrobin を選択でき、レプリカ間のキャッシュ局所性を最大化できる。
Prefillerポッド
vLLMワーカーにLMCacheをKVコネクターとして組み込んだ構成。長文プロンプトのKVキャッシュを計算し、LMCacheのPD送信バックエンドを通じてレイヤーごとにDecoderへ転送する。演算と転送をオーバーラップさせることでGPUの稼働率を維持する。
また、CPUメモリ上のローカルキャッシュも持つ。システムプロンプトやマルチターン履歴など同じプレフィックスが再登場した場合、GPUで再計算せずCPUメモリから提供できるため、TTFT(Time to First Token)の改善につながる。
Decoderポッド
KV転送を受信するvLLMワーカー。PD_BUFFER_SIZEで設定されたGPUメモリを受信バッファとして確保し、転送完了後すぐに生成を開始する。Prefill処理を一切行わないため、長文リクエストが追加されても、すでにストリーミング中のレスポンスのトークン生成速度が乱れない。
KV転送スタック
LMCache PD → NIXL → libfabric → EFA
NIXLがGPU・CPU・リモートピア間のメモリ抽象化を担い、libfabricプロバイダーがEFAをカーネルバイパス・GPU-Direct RDMAとして公開する。ホストCPUはデータパスから外れる。
ml.p5.48xlarge(EFA帯域3,200 Gbps)上での実測値として、Llama 3.3 70Bの8,000トークン分のKV転送はシングルデジット・ミリ秒(一桁ミリ秒台)とされており、Prefill計算コストに対して転送コストは無視できるレベルだ。
実際のデプロイ手順
前提条件
- HyperPod Inference Operator v3.2以上(新規EKSクラスターにはデフォルトでインストール済み)
- RDMAおよびEFAに対応したインスタンス(P5ファミリーなど)
- 同一AZ内にインスタンスを配置すること(EFA高帯域通信の要件)
バージョン確認コマンド:
kubectl get deployment hyperpod-inference-operator-controller-manager \
-n hyperpod-inference-system \
-o jsonpath='{.spec.template.spec.containers[?(@.name=="manager")].image}{"\n"}'
ワーカーイメージ
DPD対応イメージとして現時点で2択が提供されている。
- オープンソース版LMCache:
lmcache/vllm-openai:v0.4.3 - SageMaker DLC:
vllm:server-hyperpod-cuda-v1.1
モデルのS3配置とマニフェスト適用
モデルはHugging Faceからダウンロードしてs3へ同期しておく(hf download → aws s3 sync の手順)。マニフェストで重要なのがspec.pdSpecフィールドだ。このフィールドの存在がエンドポイントを分離構成にするトリガーとなる。
replicas:PrefillとDecodeを独立してスケールroutingThreshold:分離パスに振り分けるトークン数の閾値args:ロールごとのvLLMフラグ(prefillSpec・decodingSpecに個別設定可能)
マニフェストをapplyすると、Operatorがnamespace内にPrefill/Decode用の2つのDeploymentと、hyperpod-inference-systemにルーターDeploymentを作成する。
kubectl apply -f inference_endpoint_dpd_config.yaml
正常起動後は以下で状態を確認できる。
kubectl get inferenceendpointconfig ${DEPLOYMENT_NAME} -n ${NAMESPACE} \
-o jsonpath='{.status.conditions[0].message}{"\n"}'
# → DPD prefill and decode deployments are ready
どういうワークロードに向くか
DPDが効果を発揮するのは以下の条件が揃うケースだ。
- 入力プロンプトが定常的に4,096トークンを超える
- 複数ユーザーが同時リクエストを送る
- ストリーミングレスポンスでの安定したトークン配信が求められる
- 長文・短文が混在するトラフィック
逆に、バッチ・オフライン処理や低並列・短文専用のワークロードでは、KVキャッシュ転送の固定コストがメリットを上回るため、シンプルなコロケーション構成の方が合理的だとされている。
詳細はDisaggregated prefill and decode for LLM inference on SageMaker HyperPodを参照していただきたい。