跳到主要内容
推理优化

7.6 vLLM Disaggregated Prefill 实战:解耦部署与互扰量化

完整演练:混合基线测量 → P/D 解耦部署(双实例 + KV Connector)→ 互扰量化对比 → Goodput 测量 → P/D 配比推导

实战Disaggregated PrefillKV Connector互扰量化Goodput配比

7.1-7.5 讲完了原理、方案、传输、指标、配比,这一节把它们串成一次完整的实战:先用混合架构测量”干扰基线”(7.1 的问题真实存在吗),再部署 vLLM 的 Disaggregated Prefill(7.3 的 Connector 落地),最后用 Goodput 方法(7.4)量化解耦收益、推导 P/D 配比(7.5)。做完这一节,你就有了”评估要不要解耦”的标准流程。

📑 目录


1. 实验设计:先定义问题再动手

实验目标:判断”我的混合部署有没有 prefill 干扰问题,解耦能不能解决”。

实验变量

固定说明
模型LLaMA-2/3 13B 或 70B(自选)与生产一致
压测负载混合负载:长 prompt(2-4K)+ 短 prompt 混发模拟真实场景
SLOTTFT 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 记录基线

指标P50P90P95P99
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______尾部改善核心指标

判读规则

  1. TPOT P99 下降明显(如 300ms → 80ms)→ 干扰被消除,解耦在”尾部”上赢了
  2. TTFT 微增(传输成本,7.3 的账:13B/1K prompt 约 0.8GB,IB 下约 18ms)→ 预期内
  3. 两者综合:若 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):

NP=20×20003000×0.719,ND=20×500800×0.718N_P = \frac{20 \times 2000}{3000 \times 0.7} \approx 19, \quad N_D = \frac{20 \times 500}{800 \times 0.7} \approx 18

验证方法:按建议配比部署 → 压测 → 检查两端利用率与 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 上限怎么找?解耦没赢时你会怎么处理?
  • 用你的真实负载数据走一遍配比公式?
  • 上生产前要演练哪三类故障?

📚 参考资料