7.6 vLLM Disaggregated Prefill 实战:解耦部署与互扰量化
完整演练:混合基线测量 → P/D 解耦部署(双实例 + KV Connector)→ 互扰量化对比 → Goodput 测量 → P/D 配比推导
7.1-7.5 讲完了原理、方案、传输、指标、配比,这一节把它们串成一次完整的实战:先用混合架构测量”干扰基线”(7.1 的问题真实存在吗),再部署 vLLM 的 Disaggregated Prefill(7.3 的 Connector 落地),最后用 Goodput 方法(7.4)量化解耦收益、推导 P/D 配比(7.5)。做完这一节,你就有了”评估要不要解耦”的标准流程。
📑 目录
- 1. 实验设计:先定义问题再动手
- 2. 第 1 步:混合架构基线测量
- 3. 第 2 步:部署 Disaggregated Prefill
- 4. 第 3 步:互扰量化对比
- 5. 第 4 步:Goodput 测量与收益判定
- 6. 第 5 步:P/D 配比推导与验证
- 7. 常见坑位与验收清单
- 📝 总结
- 🎯 自我检验清单
- 📚 参考资料
1. 实验设计:先定义问题再动手
实验目标:判断”我的混合部署有没有 prefill 干扰问题,解耦能不能解决”。
实验变量:
| 项 | 固定 | 说明 |
|---|---|---|
| 模型 | LLaMA-2/3 13B 或 70B(自选) | 与生产一致 |
| 压测负载 | 混合负载:长 prompt(2-4K)+ 短 prompt 混发 | 模拟真实场景 |
| SLO | TTFT P95 < 2s;TPOT P95 < 100ms | 按业务设定 |
| 并发 | 固定(如 64) | 保持可复现 |
实验流程(每步的产出就是下一步的输入):
混合基线 → 解耦部署 → 互扰量化 → Goodput 对比 → 配比验证
(1) (2) (3) (4) (5)
💡 提示:这是 7.4 说的”Goodput 压测”的完整版——所有对比都基于分位点延迟曲线,不比较均值。实验全程记录 P50/P90/P95/P99,最后用达标率说话。
2. 第 1 步:混合架构基线测量
2.1 部署
# 混合架构:单实例,Continuous Batching 默认行为
vllm serve meta-llama/Llama-3.1-13B-Instruct \
--tensor-parallel-size 1 \
--max-model-len 8192 \
--max-num-seqs 64
2.2 压测
用混合负载(部分长 prompt + 部分短 prompt),vLLM benchmark 工具支持自定义 prompt 长度分布:
python3 benchmark_serving.py \
--model meta-llama/Llama-3.1-13B-Instruct \
--num-prompts 1000 \
--max-concurrency 64 \
--request-rate 10
# 长 prompt 用 --prompt-len 或自定义数据集(混合长度)
2.3 记录基线
| 指标 | P50 | P90 | P95 | P99 |
|---|---|---|---|---|
| TTFT | ___ | ___ | ___ | ___ |
| TPOT | ___ | ___ | ___ | ___ |
| 达标率(SLO) | ___ |
基线判读(对照 7.1 的信号清单):
- TPOT 的 P95-P99 明显高于 P50(如 P50 40ms、P99 300ms+)→ 干扰特征明显
- 单独压”纯短 prompt”和”纯长 prompt”对比 → 长 prompt 压测时短请求的 TPOT 是否恶化?
📌 关键点:基线测量要回答的问题不是”快不快”,而是”尾部是否被 prefill 打爆”。判读技巧:把压测拆成两段——只发短请求(无干扰参照)、混发长请求(有干扰),两次的 TPOT P99 之差就是干扰的量化值。
3. 第 2 步:部署 Disaggregated Prefill
3.1 双实例启动
# Prefill 实例(只做 prefill)
vllm serve meta-llama/Llama-3.1-13B-Instruct \
--kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_producer",
"kv_connector_extra_config":{"backends":["UCX"]}}' \
--max-model-len 8192
# Decode 实例(只做 decode)
vllm serve meta-llama/Llama-3.1-13B-Instruct \
--kv-transfer-config '{"kv_connector":"NixlConnector","kv_role":"kv_consumer",
"kv_connector_extra_config":{"backends":["UCX"]}}' \
--max-model-len 8192
(v0.26 起 --kv-role 也可用:kv_producer / kv_consumer / kv_both;单机演示可用 kv_both + 同一 config 简化。)
3.2 验证链路
检查项 1:实例启动日志
INFO ... [kv_transfer] KV connector: NixlConnector, role: kv_producer
检查项 2:功能验证
# 发一个请求,确认响应完整、长度正确
curl http://localhost:8000/v1/completions -d '{"prompt":"Hello","max_tokens":32}'
检查项 3:传输是否真的发生
# P 实例侧:传输时的网络/内存流量
nvidia-smi dmon | grep -i copy
# 或看 NIXL 的日志统计(send/recv 次数)
💡 提示:单机验证用
kv_both(一个实例同时扮演 producer/consumer)能省一台机器,但生产必须拆成两个独立角色。另注意 v0.26 中 Disaggregated Prefill 是 experimental——文档明确”参数可能变化”,以当前版本文档为准。
3.3 独立调参的验证
解耦的核心卖点是”两个实例独立调参”——顺手验证:
# P 实例换 TP=2(prefill 算力优先)
# D 实例保持 TP=1(decode 带宽优先)
# 对比 TTFT 变化是否只影响 TTFT、TPOT 变化是否只影响 TPOT
预期:P 实例加 TP 后 TTFT 下降,TPOT 基本不动——这就是”旋钮解耦”的直接证明。
4. 第 3 步:互扰量化对比
用相同负载(2.2 的混合负载)压解耦部署,得到第二条曲线:
| 指标 | 混合基线 P95 | 解耦 P95 | 变化 |
|---|---|---|---|
| TTFT | ___ | ___(应略增,含传输) | 传输成本 |
| TPOT | ___ | ___(应显著下降) | 干扰消除 |
| TPOT P99 | ___ | ___ | 尾部改善核心指标 |
判读规则:
- TPOT P99 下降明显(如 300ms → 80ms)→ 干扰被消除,解耦在”尾部”上赢了
- TTFT 微增(传输成本,7.3 的账:13B/1K prompt 约 0.8GB,IB 下约 18ms)→ 预期内
- 两者综合:若 TTFT 增量 << TPOT 尾部改善 × 输出长度 → 解耦净收益为正
📌 关键点:第 4 步的对比要同负载、同并发、同 SLO——这是 7.4 的 Goodput 对比纪律。输出长度越长,解耦的净收益越大(7.3 第 2.3 节),所以如果负载是”短输出”,第 4 步的结论可能反转——这是正常且重要的发现。
5. 第 4 步:Goodput 测量与收益判定
5.1 加压找 Goodput 上限
对两种架构分别加压(逐步提高 request-rate),记录每个压力点的 P95 延迟:
| 压力(req/s) | 混合 P95 TTFT | 混合 P95 TPOT | 解耦 P95 TTFT | 解耦 P95 TPOT |
|---|---|---|---|---|
| 5 | ||||
| 10 | ||||
| 20 | ||||
| 40 |
Goodput 上限 = P95 曲线与 SLO 线的交点(7.4 第 4 节)。
5.2 收益判定表
| 指标 | 混合 | 解耦 | 结论 |
|---|---|---|---|
| Goodput(满足 SLO 的 req/s) | ___ | ___ | 解耦收益 = 差值 |
| 达标率 @ 目标负载 | ___ | ___ | 解耦后是否回到 99%+ |
| 成本(总 GPU 数) | ___ | ___ | 解耦是否更费卡(7.5 配比) |
💡 提示:诚实的结论有时是”解耦没赢”——比如短输出负载下,传输成本吃掉了尾部收益,Goodput 反而下降。这不是失败,是数据:它告诉你当前负载不需要解耦(7.5 的决策框架)。把实验流程和结论存档,负载变化后重跑。
6. 第 5 步:P/D 配比推导与验证
6.1 收集单卡能力
在解耦部署上分别测单卡能力(7.5 公式的输入):
# P 池单卡 prefill 吞吐:纯长 prompt 压测,看 prefill 阶段 token/s
# D 池单卡 decode 吞吐:固定并发压测,看 decode token/s
6.2 代入公式
以 7.5 的对话负载为例(R=20、Lp=2K、Ld=500、P_prefill=3K、P_decode=800、u=0.7):
验证方法:按建议配比部署 → 压测 → 检查两端利用率与 SLO:
- P 池利用率 ~70% 且 TTFT 达标 → 配比合理
- P 池利用率 95%+ 且 TTFT 超标 → 加 P 池(N_P 上调)
- P 池利用率 30% → 缩 P 池(余量过大,浪费)
6.3 弹性预案
按 7.5 的弹性策略预留:P 池高峰扩、低峰缩;D 池按并发伸缩。配比文档化(输入/输出/假设),负载漂移时重跑。
📌 关键点:第 5 步是”从实验到生产”的桥梁——前面 4 步证明”解耦值得”,这一步回答”值得多少卡”。注意配比是服务级参数(随负载变),不是一次性的架构决策。
7. 常见坑位与验收清单
7.1 坑位图
| 症状 | 根因 | 处理 |
|---|---|---|
| TTFT 异常高(比混合还差) | 传输走了慢网络 / NIXL 未生效 | 检查网络与 kv_connector 配置;确认 UCX/RDMA 可用 |
| 响应内容不对(乱码/截断) | KV 传输不完整 | 检查 block 粒度与 kv_buffer_device(cuda/cpu) |
| D 实例空等卡死 | P 实例失败/超时,孤儿请求 | 检查失败处理与超时配置 |
| TPOT 没改善 | 负载本来就是短输出 / 干扰本就不存在 | 回看基线判读(第 2 步),可能不需要解耦 |
| 多卡 TP 下 KV 传输错乱 | TP 组内 KV 分片与 Connector 不匹配 | 确认 P/D 实例 TP 配置与文档约束一致 |
7.2 验收清单
- 基线测量完成(混合负载、分位点曲线、SLO 达标率)
- 解耦部署双实例启动成功、功能验证通过
- 互扰量化完成(TPOT P99 对比,干扰值量化)
- Goodput 对比完成(SLO 交点、收益判定)
- 配比推导文档化(公式、输入、结论)
- 故障演练:P 实例挂、传输断、D 缩容各有预期行为
- 结论明确:解耦 or 不解耦,以及原因
💡 提示:整个实验流程的最终产出不是”部署成功”,而是一份带数据的决策报告:基线有多糟(干扰量化)、解耦改了多少(Goodput 差值)、值不值得(成本对比)。用数据说服团队(和未来的自己),这是本节真正的价值。
📝 总结
- 流程:混合基线 → 解耦部署 → 互扰量化 → Goodput 对比 → 配比验证
- 基线判读:长/短请求分开压,差值 = 干扰量化值;看 P99 不看均值
- 部署:双实例 +
--kv-transfer-config(NixlConnector 起步),kv_producer/kv_consumer - 独立调参验证:P 池 TP 只动 TTFT——旋钮解耦的直接证明
- Goodput 判定:P95 曲线与 SLO 线交点,诚实记录”解耦没赢”的情况
- 配比:公式代入实测单卡能力,利用率验证 + 文档化 + 弹性预案
- 产出:一份数据驱动的解耦决策报告
🎯 自我检验清单
- 写出完整的实验变量表(固定项、负载、SLO)?
- 混合基线的”干扰量化”怎么做?(长/短请求对比)
- 双实例的启动命令?
kv_producer/kv_consumer是什么? - 怎么证明”独立调参”生效?(只动 TTFT 不动 TPOT)
- Goodput 上限怎么找?解耦没赢时你会怎么处理?
- 用你的真实负载数据走一遍配比公式?
- 上生产前要演练哪三类故障?
📚 参考资料
- vLLM 官方文档:Disaggregated Prefilling(https://docs.vllm.ai/en/latest/features/disagg_prefill.html)
- vLLM 官方示例:examples/disaggregated/(example_connector、lmcache、nixl_integration)(https://github.com/vllm-project/vllm/tree/v0.26.0/examples/disaggregated)
- vLLM 官方文档:NIXL Connector Usage Guide(https://docs.vllm.ai/en/latest/features/nixl_connector_usage.html)
- vLLM benchmark_serving 工具(https://github.com/vllm-project/vllm/tree/v0.26.0/benchmarks)
- Zhong et al., DistServe(Goodput 测量方法)(https://www.usenix.org/conference/osdi24/presentation/zhong-yinmin)