本記事は DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving(arXiv:2403.02310、2024年3月公開)の解説記事です。
論文概要(Abstract)
DistServeは、LLM推論のPrefillフェーズ(プロンプト処理)とDecodeフェーズ(トークン逐次生成)を物理的に異なるGPUインスタンスに分離(Disaggregation)することで、Goodput(SLOを満たすリクエスト/秒) を最大化するサービングシステムである。著者らは、PrefillとDecodeが異なる計算特性(Prefill: compute-bound、Decode: memory-bound)を持つにもかかわらず、既存システムが両フェーズを同一GPU上で混在処理している問題を指摘し、物理分離による個別最適化を提案している。
この記事は Zenn記事: Azure OpenAI負荷分散設計:API ManagementとPTUスピルオーバーで可用性99.9%を実現する の深掘りです。
情報源
- arXiv ID: 2403.02310
- URL: https://arxiv.org/abs/2403.02310
- 著者: Yinmin Zhong, Shengyu Liu, Junda Chen, Jianbo Hu, Yibo Zhu, Xuanzhe Liu, Xin Jin, Hao Zhang(Peking University, UC San Diego)
- 発表年: 2024
- 分野: cs.DC(分散コンピューティング)
背景と動機(Background & Motivation)
LLM推論は、PrefillフェーズとDecodeフェーズという本質的に異なる2つの計算段階で構成される。
- Prefillフェーズ: 入力プロンプト全体を一括処理し、KVキャッシュを生成する。計算がGPU演算性能(FLOPs)に律速されるcompute-boundな処理。
- Decodeフェーズ: トークンを1つずつ逐次生成する。KVキャッシュの読み出しがGPUメモリ帯域に律速されるmemory-boundな処理。
既存のLLMサービングシステム(vLLM、Orca等)は、PrefillとDecodeを同一GPU上でインターリーブ実行する。この混在処理では、Prefillの大量計算がDecodeのレイテンシを悪化させ(head-of-line blocking)、逆にDecodeの小さなバッチがPrefillのスループットを低下させる。
著者らは、この問題をSLO(Service Level Objectives)違反として定量化している。LLM推論のSLOは通常2つの指標で定義される:
- TTFT SLO: Time to First Token(最初のトークンまでの時間)の上限
- TPOT SLO: Time Per Output Token(トークンあたりの生成時間)の上限
混在処理では、高負荷時にTTFTまたはTPOTのSLOを満たせないリクエストが増加し、Goodput(SLOを満たすリクエスト/秒) が低下する。
主要な貢献(Key Contributions)
- 貢献1: Goodputという新しい性能指標の提案。従来のスループット(全リクエスト/秒)ではなく、SLOを満たすリクエスト数で性能を評価する。
- 貢献2: Prefill/Decode分離アーキテクチャの設計と実装。KVキャッシュ転送メカニズムを含む完全なシステムを構築。
- 貢献3: Prefill/Decodeインスタンス比率の最適化アルゴリズム。ワークロード特性に応じた最適リソース配分を自動決定。
技術的詳細(Technical Details)
アーキテクチャ
DistServeのアーキテクチャは以下の通りである。
1
2
3
4
5
6
7
8
9
10
11
12
13
┌─────────────────┐
│ Dispatcher │
│ (リクエスト受付) │
└────────┬────────┘
│
┌─────────────┴─────────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Prefill Workers │ │ Decode Workers │
│ (compute-bound) │ │ (memory-bound) │
│ │───────>│ │
│ GPU: 高FLOPs重視│ KVキャッシュ│ GPU: 高帯域重視 │
└──────────────────┘ 転送 └──────────────────┘
Dispatcher: 新規リクエストをPrefill Workerに送信。Prefill完了後、KVキャッシュとともにDecode Workerに転送。
Goodputの定式化
Goodputは以下のように定義される。
\[\text{Goodput} = \frac{|\{r \in R : \text{TTFT}(r) \leq T_{\text{TTFT}} \land \text{TPOT}(r) \leq T_{\text{TPOT}}\}|}{T_{\text{observe}}}\]ここで、
- $R$: 観測期間中の全リクエスト集合
- $\text{TTFT}(r)$: リクエスト$r$の最初のトークンまでの時間
- $\text{TPOT}(r)$: リクエスト$r$のトークンあたり生成時間
- $T_{\text{TTFT}}, T_{\text{TPOT}}$: それぞれのSLO閾値
- $T_{\text{observe}}$: 観測期間
| 従来のスループットは$ | R | / T_{\text{observe}}$であるが、GoodputはSLO違反リクエストを除外することで、実際にユーザー体験を満たすリクエストの処理能力を測定する。 |
Prefill/Decode分離の計算特性分析
著者らは、PrefillとDecodeの計算特性を以下のように分析している。
Prefillフェーズの計算量:
\[\text{FLOPs}_{\text{prefill}} = 2 \times n_{\text{params}} \times s_{\text{input}}\]ここで$n_{\text{params}}$はモデルパラメータ数、$s_{\text{input}}$は入力シーケンス長。入力が長いほどFLOPsが線形に増加するcompute-bound処理。
Decodeフェーズの計算量:
\[\text{FLOPs}_{\text{decode}} = 2 \times n_{\text{params}} \times 1\]1トークンずつの逐次生成であり、FLOPsは入力長に依存しない。ボトルネックはKVキャッシュの読み出し(メモリ帯域)に移行するmemory-bound処理。
この特性差により、Prefillワーカーには高FLOPsのGPU(例: H100)を、DecodeワーカーにはHBM帯域の高いGPU(例: A100 80GB)を割り当てる異種GPU構成が有効になる。
KVキャッシュ転送メカニズム
Prefill完了後、生成されたKVキャッシュをDecodeワーカーに転送する必要がある。KVキャッシュのサイズは以下で計算される。
\[\text{KV Size} = 2 \times L \times H \times d_k \times s \times \text{dtype\_size}\]OPT-66Bモデル($L=64, H=72, d_k=128$)でシーケンス長512の場合、KVキャッシュは約4.7GBとなる。InfiniBand (200 Gbps)接続では転送に約190msを要する。
著者らは、この転送オーバーヘッドを最小化するため、パイプライン化されたKVキャッシュ転送を実装している。Prefillの計算と並行してKVキャッシュの転送を開始し、最後のレイヤーの処理完了と同時に転送を完了させる。
リソース配分最適化
著者らは、Prefill/Decodeインスタンスの最適比率を決定するアルゴリズムを提案している。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def optimize_resource_allocation(
total_gpus: int,
workload: WorkloadTrace,
ttft_slo: float,
tpot_slo: float
) -> tuple[int, int]:
"""Prefill/Decodeの最適GPU配分を決定
Args:
total_gpus: 利用可能なGPU総数
workload: ワークロードトレース
ttft_slo: TTFT SLO閾値(秒)
tpot_slo: TPOT SLO閾値(秒)
Returns:
(prefill_gpus, decode_gpus) の最適配分
"""
best_goodput = 0
best_allocation = (0, 0)
for prefill_gpus in range(1, total_gpus):
decode_gpus = total_gpus - prefill_gpus
# シミュレーションでGoodputを推定
goodput = simulate_goodput(
prefill_gpus, decode_gpus,
workload, ttft_slo, tpot_slo
)
if goodput > best_goodput:
best_goodput = goodput
best_allocation = (prefill_gpus, decode_gpus)
return best_allocation
実装のポイント(Implementation)
vLLMベースの実装
DistServeはvLLMをベースに実装されており、主要な変更点は以下の通りである:
- スケジューラの分離: Prefill用スケジューラとDecode用スケジューラを個別に実装
- KVキャッシュ転送レイヤー: NCCL(NVIDIA Collective Communications Library)を使用したGPU間通信
- Dispatcherの実装: gRPCベースのリクエストルーティング
バッチサイズの個別最適化
分離アーキテクチャの利点として、PrefillとDecodeのバッチサイズを独立に最適化できる点がある:
- Prefillバッチ: 大きなバッチサイズでGPU利用率を最大化(compute-bound)
- Decodeバッチ: 大きなバッチサイズでメモリ帯域利用率を最大化(memory-bound)
混在処理では両フェーズのバッチサイズが相互に制約を受けるが、分離により各フェーズが独立に最適バッチサイズを選択できる。
実験結果(Results)
著者らの実験はOPT-13B / OPT-66B / OPT-175Bモデル、A100 GPUクラスターで実施されている。
主要な実験結果(論文Table 2, Figure 8より):
| 構成 | TTFT SLO | TPOT SLO | vLLM Goodput | DistServe Goodput | 改善率 |
|---|---|---|---|---|---|
| OPT-13B | 1秒 | 0.2秒 | 3.2 req/s | 14.3 req/s | 4.48x |
| OPT-66B | 2秒 | 0.3秒 | 1.1 req/s | 3.8 req/s | 3.45x |
| OPT-175B | 5秒 | 0.5秒 | 0.4 req/s | 1.2 req/s | 3.0x |
著者らは、改善の主因としてhead-of-line blockingの解消を挙げている。混在処理では長いPrefillが後続のDecodeステップをブロックしてTPOT SLO違反を引き起こすが、分離によりDecodeワーカーはPrefillの影響を受けずに一定のTPOTを維持できる。
KVキャッシュ転送のオーバーヘッド:
- InfiniBand 200 Gbps: 平均180ms(OPT-66B、シーケンス長512)
- NVLink: 平均50ms(同一ノード内の場合)
著者らの報告では、転送オーバーヘッドはGoodput改善に対して十分に小さく、分離のメリットがコストを上回るとのことである(論文§5.3)。
実運用への応用(Practical Applications)
Azure OpenAIの容量計画との関連
DistServeの知見は、Azure OpenAIのPTU容量計画に以下の形で応用可能である。
Goodput指標の適用: PTUの容量を「処理可能なリクエスト/秒」ではなく「SLOを満たすリクエスト/秒(Goodput)」で評価する。PTU利用率が高くてもSLO違反が頻発していれば、PTUの追加が必要。
Prefill/Decodeの負荷バランス考慮: Azure OpenAIの内部実装がPrefill/Decode分離を採用している場合(公開情報なし)、長いプロンプトのリクエストはPrefillリソースを多く消費し、短いプロンプトのリクエストはDecodeリソースを主に消費する。この特性を理解することで、ワークロードの特性に応じたPTU量の見積もりが精緻化できる。
SLO設計の定量的根拠: DistServeが提案するTTFT/TPOTの2指標は、Azure OpenAIのSLA設計やアラート閾値の設定に直接適用可能である。
自前LLMクラスターでの活用
vLLMのdisaggregated_prefillブランチが参考実装として利用可能である。
関連研究(Related Work)
- vLLM (Kwonら, 2023): PagedAttentionによるKVキャッシュ管理。DistServeのベースエンジン。
- Sarathi-Serve (Agrawalら, 2023, arXiv:2312.11514): Chunked PrefillによるPrefill/Decodeのインターリーブ最適化。DistServeとは直交するアプローチ(混在処理の改善 vs 物理分離)。
- Llumnix (Sunら, 2024, arXiv:2401.12843): 動的リクエストマイグレーション。DistServeとの組み合わせ(分離されたワーカー間での動的再配置)が考えられる。
Production Deployment Guide
AWS実装パターン(コスト最適化重視)
DistServeのPrefill/Decode分離アーキテクチャをAWSで実現する構成を示す。
トラフィック量別の推奨構成:
| 規模 | 月間リクエスト | 推奨構成 | 月額コスト | 主要サービス |
|---|---|---|---|---|
| Small | ~3,000 | Serverless | $50-150 | Lambda + Bedrock(分離不要) |
| Medium | ~30,000 | Hybrid | $1,000-3,000 | ECS Fargate + vLLM |
| Large | 300,000+ | Container | $5,000-15,000 | EKS + vLLM DistServe + GPU Spot |
Large構成の詳細 (月額$5,000-15,000):
- EKS: コントロールプレーン ($72/月)
- Prefillノード: p4d.24xlarge (A100 80GB × 8) × 1台 ($10,000/月 On-Demand、Spot $3,000/月)
- Decodeノード: g5.12xlarge (A10G × 4) × 2台 ($4,000/月 On-Demand、Spot $1,200/月)
- 高速Interconnect: EFA (Elastic Fabric Adapter)対応インスタンス
コスト試算の注意事項:
- 上記は2026年2月時点のAWS料金に基づく概算値です
- GPU Spot Instancesの価格は需給により大きく変動します
- 最新料金は AWS料金計算ツール で確認してください
Terraformインフラコード
EKS + vLLM DistServe構成:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# Prefillノード用Node Group
resource "aws_eks_node_group" "prefill" {
cluster_name = module.eks.cluster_name
node_group_name = "prefill-workers"
node_role_arn = aws_iam_role.node.arn
subnet_ids = module.vpc.private_subnets
instance_types = ["p4d.24xlarge"] # A100 80GB x 8
capacity_type = "SPOT"
scaling_config {
desired_size = 1
max_size = 2
min_size = 0
}
labels = {
"distserve/role" = "prefill"
}
taint {
key = "nvidia.com/gpu"
value = "true"
effect = "NO_SCHEDULE"
}
}
# Decodeノード用Node Group
resource "aws_eks_node_group" "decode" {
cluster_name = module.eks.cluster_name
node_group_name = "decode-workers"
node_role_arn = aws_iam_role.node.arn
subnet_ids = module.vpc.private_subnets
instance_types = ["g5.12xlarge"] # A10G x 4
capacity_type = "SPOT"
scaling_config {
desired_size = 2
max_size = 4
min_size = 0
}
labels = {
"distserve/role" = "decode"
}
taint {
key = "nvidia.com/gpu"
value = "true"
effect = "NO_SCHEDULE"
}
}
コスト最適化チェックリスト
- Prefillノードは高FLOPs GPU(A100/H100)、Decodeノードは高HBM帯域GPU(A100 80GB)を選択
- GPU Spot Instances使用で最大70-90%削減
- Karpenterでアイドル時自動スケールダウン
- EFA対応インスタンスでKVキャッシュ転送高速化
- Prefill/Decode比率をワークロードに合わせて最適化
- CloudWatch GPUメトリクスで利用率監視
- AWS Budgets月額予算設定
まとめと今後の展望
DistServeは、LLM推論のPrefill/Decode分離という設計判断により、Goodputを最大4.48倍改善したことを報告している(論文Table 2より)。この結果は、LLM推論の2つのフェーズが本質的に異なる計算特性を持ち、個別最適化の余地が大きいことを実証している。
Azure OpenAIの文脈では、以下の形で本論文の知見を活用できる:
- PTUの容量評価を「リクエスト/秒」から「Goodput(SLO達成リクエスト/秒)」に精緻化する
- ワークロードのプロンプト長分布がPrefillリソース消費に与える影響を考慮したPTU見積もり
- TTFT/TPOTの2軸SLO設計による運用アラートの最適化
今後の研究方向として、著者らは動的なPrefill/Decode比率調整やエネルギー効率を考慮したリソース配分を挙げている。
参考文献
- arXiv: https://arxiv.org/abs/2403.02310
- Related: Sarathi-Serve (arXiv:2312.11514) — Chunked Prefillによる代替アプローチ
- Related Zenn article: https://zenn.dev/0h_n0/articles/838465e8c756eb
:::message この記事はAI(Claude Code)により自動生成されました。論文の内容は原著者の主張を要約・解説したものであり、本記事の著者が独自に実験を行ったものではありません。正確な数値・詳細は原論文をご確認ください。 :::