Prefill/Decode 分离:让算力和带宽各管各的
谁该读这一篇? TTFT 和 TPOT 的 SLO 同时卡得很紧、单 server 调不出来的工程师。 前置阅读:
00-prerequisites.md§2、03-code-walkthrough/03-scheduler.md。 耗时: 35 分钟 学完能: 1. 说出为什么 prefill 和 decode 共跑会互相拖累; 2. 画出 P/D 分离的数据流(KV transfer); 3. 区分 RDMA / NIXL / NCCL 三种 KV transfer 介质; 4. 判断业务是否值得开 P/D 分离; 5. 在 SGLang 启用 disagg 模式。
1. 问题陈述
普通模式(合一)下,一个 server 同时跑 prefill 和 decode 请求:
- Prefill 算力密集(每 token 大量 matmul)。
- Decode 带宽密集(每步 1 token,矩阵瘦)。
把两者放同一 batch(chunked prefill 模式)能提 GPU 利用率,但有副作用:
- Prefill 长 prompt 时占满 token budget,decode 被抢占→ TPOT 抖动。
- Decode 大量请求时 attention kernel 被 decode 的 indirection 干扰,prefill 慢。
如果你的业务对TTFT 和 TPOT 都有硬性 SLO(如 chat 服务),合一模式很难同时满足。
2. P/D 分离
Prefill Server (A) Decode Server (B)
─ 专跑 prompt prefill ─ 专跑 token 生成
─ 不持有 long KV ─ 持有 KV cache 直到 EOS
─ 算力满载 ─ 带宽满载
│ ▲
└─── KV transfer ──────────┘
(RDMA / NIXL)
请求生命周期:
- 进 router,分流到一个 Prefill 节点。
- Prefill 完成,KV 通过 RDMA 推送到 Decode 节点。
- Decode 节点接管,开始 token 生成。
- 完成后返回。
收益:
- TTFT 受 Prefill 服务直接控制(不被 decode 抢算力)。
- TPOT 受 Decode 服务直接控制(不被 prefill 抢算力)。
- 两类节点资源比例可以独立调(如 1 prefill : 3 decode)。
代价:
- KV 跨节点传输开销(短请求得不偿失)。
- 部署复杂度大幅上升。
3. SGLang 当前支持
主要文件:
disaggregation/
├── decode.py ← Decode 节点主体
├── prefill.py ← Prefill 节点主体
├── decode_kvcache_offload_manager.py
├── decode_schedule_batch_mixin.py
├── encode_server.py ← Encoder 单独分离(多模态)
├── encode_grpc_server.py
├── common/
└── fake/ ← 测试用 mock
启动两套:
# Prefill 节点
python -m sglang.launch_server \
--model-path Qwen/Qwen2.5-72B-Instruct \
--disaggregation-mode prefill \
--disaggregation-bootstrap-port 8998 \
--tp 8 --port 30000
# Decode 节点
python -m sglang.launch_server \
--model-path Qwen/Qwen2.5-72B-Instruct \
--disaggregation-mode decode \
--disaggregation-bootstrap-port 8998 \
--tp 8 --port 30001
bootstrap-port 是两边握手用的端口。
4. KV Transfer:怎么跨节点搬 KV
KV 的体量:
- Llama-3-70B 单 token KV ≈ 320 KiB。
- 一个 4k prompt 的 KV ≈ 1.25 GB。
- 100 QPS × 4k prompt × TTFT 1s = 125 GB/s 的瞬时 KV transfer 带宽需求。
显然需要 RDMA。
4.1 RDMA 方案
- NCCL (默认):用 NCCL 的点对点 send/recv,需要预先建好 communicator。
- NIXL(NVIDIA Inference Transfer Library):专门为 LLM inference 设计的传输库,支持 GPU Direct RDMA,自动管 buffer 池。
- Mooncake 等开源库:UCX 之上做的 KV cache 传输专用库。
SGLang 主要走 NCCL 和 NIXL 两条路径。
4.2 传输时序
T0: Prefill 完成(KV 写入 Prefill 节点的 KV pool)
T1: bootstrap 信号给 Decode(带 KV pool 元数据 + 第一个 sampled token)
T2: Decode 启动 KV transfer wait
T3: Prefill 触发 RDMA send(按 attention layer 流式)
T4: Decode 边接收边开始 decode(pipeline)
注意 T3-T4 可以 pipeline:第一层 KV 收到了就开始算第一层 decode,不需要全部收完。 这把 KV transfer 的"等待"折叠进 decode 自身的 forward 时间,TTFT 影响 < 50ms。
5. 容量与流量比例
prefill 算力 vs decode 算力的比例:
例:
- 1k 输入 / 100 输出:比例 = 10
- 4k 输入 / 200 输出:比例 = 20
但 prefill 算力效率高(接近 peak),decode 带宽受限,实际 throughput 比 ≈ 比例 / 5。
经验:
- 短输入 / 长输出(如 chat):Prefill : Decode = 1 : 3 或 1 : 4。
- 长输入 / 短输出(如总结):Prefill : Decode = 2 : 1。
业务流量分析后定比例。
6. Router 怎么协调
SGLang router 在 disagg 模式下:
Client → Router
├──→ 选择 Prefill 节点 P_i (cache-aware)
├──→ 提示 Decode 节点 D_j 准备接收 KV
└──→ Prefill 完成后 D_j 开始 decode,stream 回 Router → Client
Router 维护"哪个 D_j 当前空闲度高"的状态,做配对。
--disaggregation-mode null 是普通合一模式(router 透传)。
7. 何时不该开 P/D 分离
- 单轮短请求(<512 prompt + <128 output):KV transfer 开销大于收益。
- 业务流量小,单节点能扛:增加部署复杂度不值得。
- 团队没有 RDMA 运维能力:故障难定位。
何时该开:
- 长 prompt + 长输出,TTFT + TPOT 都卡。
- 业务流量大,单节点扛不住。
- 已经有成熟 RDMA 网络。
8. Encoder 分离(多模态)
对于多模态模型,encoder(ViT 等)和 decoder(LLM)也可以分离:
# Encoder 节点
python -m sglang.launch_server \
--model-path Qwen/Qwen2-VL-72B-Instruct \
--encoder-only \
--port 30100
# Decoder 节点
python -m sglang.launch_server \
--model-path Qwen/Qwen2-VL-72B-Instruct \
--disaggregation-mode decode \
--port 30000
源码:encode_server.py、encode_grpc_server.py。
收益:图像处理用专用 ViT 节点(不需大显存),decoder 节点专注 LLM。
9. 监控指标
sglang:disagg_prefill_to_decode_latency_ms # KV 传输 + 握手耗时
sglang:disagg_kv_transfer_throughput_gb_s
sglang:disagg_prefill_queue_size
sglang:disagg_decode_queue_size
健康:
- prefill_to_decode latency p99 < 200 ms。
- KV throughput 接近网卡带宽。
10. 排障
| 现象 | 排查 |
|---|---|
| 启动卡在 bootstrap | 端口防火墙 / 节点间网络 |
| KV transfer 慢 | RDMA 没启用;NCCL 走 TCP |
| Decode 节点等很久 | Prefill 队列长;增 prefill 节点 |
| 请求丢失 | Router 路由 bug;查 router 日志 |
11. 小结
- P/D 分离把 prefill 和 decode 拆到不同节点,TTFT 和 TPOT 分别优化。
- KV transfer 是关键,需要 RDMA / NIXL。
- 适合长 prompt + 长输出、流量大、SLO 双卡场景。
- SGLang 当前支持 disagg prefill / decode + encoder 分离。
- 部署复杂度显著上升,团队要有 RDMA 经验。
12. 自检
- P/D 共跑的副作用是什么?分离后怎么解?
答案
共跑副作用: - **算力 vs 带宽冲突**:prefill 吃算力,decode 吃带宽;混跑时两类请求互相抢资源。 - **长 prompt 抢 decode**:一个 16k prompt 进来 prefill 几秒,期间 decode 请求 TPOT 抖动。 - **抢占级联**:KV pool 紧时 scheduler 抢占长 decode 请求腾空间,被抢的请求重新排队,加剧紧张。 分离后:prefill 节点专跑 prefill(算力满),decode 节点专跑 decode(带宽满)。TTFT 和 TPOT 解耦,各自 SLO 可独立调。代价是 KV 跨节点传输 + 部署复杂度。- KV transfer 带宽需求怎么算?
答案
单请求 KV size:`prompt_len × num_layers × 2 (K+V) × num_kv_heads × head_dim × dtype_bytes`。 Llama-3-70B 单 token: 320 KiB;4k prompt: 1.25 GB。 总带宽:`QPS × KV_per_request / TTFT`。 例:100 QPS × 4k prompt × 1.25 GB / 1s TTFT = **125 GB/s**。 IB 400 Gb/s = 50 GB/s 单向;需要多张 IB 网卡 + RDMA。 FP8 KV cache 把这个数砍半(160 KiB/token);MLA 模型砍 5-10× 更低。 所以 P/D 分离落地的硬条件:(a) 量化 KV;(b) 多张 IB;(c) 流式 transfer(边 prefill 边推 KV)。- P/D 节点数比例由什么决定?
答案
主要由 **prompt:output token 比例 + 业务流量** 决定: - 短 prompt 长 output(chat 32:200):decode 节点多。Prefill:Decode ≈ 1:3 或 1:4。 - 长 prompt 短 output(总结 4000:100):prefill 节点多。Prefill:Decode ≈ 2:1。 - 极长 prompt(agent context 16k+):prefill 算力极重,可能 5:1。 动态调:监控 prefill_queue_size 和 decode_queue_size,谁堆积扩谁。 公式估算:`ratio = (avg_prompt × prefill_flops_per_token) / (avg_output × decode_flops_per_token × decode_efficiency)`,但实战还是看 metric 调比例。- 为什么短请求不该开 P/D 分离?
答案
开销不划算: (1) **KV transfer 固定开销**:每请求要做一次跨节点 KV 推送 + bootstrap 握手,~50-200 ms。短请求总时延才 200ms-1s,transfer 开销占 20-50%。 (2) **管线收益小**:短 prompt(< 512 token)prefill 才几 ms,分离不分离影响小。 (3) **复杂度暴涨**:部署 2 倍节点 + RDMA 网络 + router 协调,运维成本激增。 什么时候开:长 prompt(4k+)+ 长 output(500+)+ TTFT 和 TPOT 双 SLO 卡紧;短请求继续合一 + chunked prefill 即可。- Encoder 分离对多模态服务的收益?
答案
(1) **专门硬件**:ViT 算力密集但不要大显存,可以用便宜的 GPU(L40 / A40),LLM 节点用 H100;总成本降 30-50%。 (2) **独立扩缩**:图像流量峰值不一定跟 chat 峰值一致;encoder 节点按图像 QPS 扩缩。 (3) **Encoder cache 共享**:多 LLM 节点复用同一 encoder 节点的 image embedding cache,热图(电商商品图)命中率高。 (4) **避免 ViT 阻塞调度**:合一时 ViT 60-120ms 编码挤占 forward stream;分离后 LLM 节点 forward 顺畅。 适合:高 QPS 多模态业务(电商搜图、内容审核)。低 QPS 单节点合一即可。13. 下一步
08-production-deployment/02-kubernetes.md— K8s 部署。08-production-deployment/07-router.md— Router 配合。08-production-deployment/05-incident-playbook.md— 故障排查。- 源码:
srt/disaggregation/。 - 横向对比:
vllm-learning/05-distributed/02-disaggregated.md。