PD 分离:大模型推理的第一步优化

是什么:PD 分离的定义

大模型推理分为两个阶段:

输入 token: ["今天", "天气", "怎么样"]

═══════ Prefill(预填充)═══════
一次性把 ["今天", "天气", "怎么样"] 送进模型
→ 输出每个 token 的 hidden state + 第一个生成 token

─────── Decode(逐token解码)───────
用上一步的输出 token 逐个生成后续 token
"今天天气怎么样" → "还" → "不" → "错" → ...
直到生成结束符 <eos>

PD 分离:把 Prefill 和 Decode 部署在不同实例上,各自优化。


为什么需要 PD 分离?

先看两个阶段的资源需求差异:

Prefill Decode
计算模式 批处理,并行处理所有输入 token 串行,一次只处理 1 个 token
瓶颈 计算密集型(compute-bound) 内存带宽型(memory-bound)
计算量/token 高(Self-Attention O(n²)) 低(每次只算一个新 token 的 Attention)
GPU 利用率 可达 80-90% 通常 10-30%
延迟特征 一次性较大延迟 每 token 固定小延迟

本质问题:Prefill 和 Decode 用同一张卡跑,资源需求完全相反——Prefill 要算力,Decode 要带宽,卡在中间谁也发挥不好。

广告系统类比

这就像把广告检索精排打分跑在同一台机器上:

检索(召回+粗排):大量候选,计算密集,可以并行
  vs
精排打分:少量候选,需要复杂模型,延迟敏感

你不会把召回和精排混在一起——召回用高性能批量引擎,精排用低延迟排序引擎。PD 分离完全一样的逻辑。


去掉 PD 分离的代价

混合部署(Prefill 和 Decode 同一实例)的典型灾难场景:

时刻 1: Prefill 任务进来,GPU 算力拉到 90%
时刻 2: Prefill 任务完成,进入 Decode → GPU 利用率骤降到 15%
时刻 3: 新用户请求进来,需要 Prefill → 但实例在跑 Decode,要等
冲突结果:Prefill 被 Decode 阻塞(延迟飙升),Decode 被 Prefill 抢占(抖动)

这就像你的广告检索系统里,一个耗时的复杂 query 把整个倒排引擎卡住了,后面 100 个简单 query 排队等着。你会怎么做?当然是拆成独立通道。

PD 分离后:

  • Prefill 实例:只管吃输入、吐 KV Cache,GPU 利用率持续 80%+
  • Decode 实例:只管逐 token 输出,内存带宽利用率持续拉满
  • 两者互不干扰,各司其职

覆盖多少场景?

PD 分离不是银弹,适用场景取决于请求特征:

场景 Prefill 占比 Decode 占比 PD 分离收益
对话机器人 低(prompt 短) 高(回复长) 中等,Decode 优化收益大
长文档摘要 高(几万字输入) 低(摘要几百字) 大,Prefill 独立扩展
代码生成 中等 大,两个阶段特征差异明显
多轮对话 高(累积历史) 最大,两个阶段都重

判断标准:当 Prefill 延迟 > Decode 每 token 延迟的 5 倍以上,或者 GPU 利用率长期 < 50%,就需要 PD 分离。


工程实践:几 P 几 D?

“几 P 几 D” 就是 Prefill 和 Decode 实例的配比。以 vLLM/SGLang 为例:

场景一:短 prompt,长输出(对话)

用户输入: "你好"  (2 tokens)
模型输出: "你好!今天想聊什么..."  (200 tokens)

Prefill 轻 / Decode 重
配比: 1P : 3D 或 1P : 4D

场景二:长文档处理

用户输入: 上传一篇论文  (20000 tokens)
模型输出: 摘要  (500 tokens)

Prefill 重 / Decode 轻
配比: 3P : 1D 或 4P : 1D

场景三:混合流量

系统中两种类型都有
配比: 2P : 2D (平均)
动态调整: 根据实时负载,自动增减 P 或 D 实例

广告系统类比

这和广告集群资源分配一模一样:

广告系统问题:
召回集群:召回量大 → 多给机器
精排集群:延迟敏感 → 用高性能机器
流量峰谷:晚高峰召回激增 → 动态扩召回集群

PD 分离的对应:
Prefill 重(长文档)→ 多给 P 实例
Decode 重(对话)→ 多给 D 实例
动态调整 → 自动扩缩容

不变的本质

PD 分离背后的三条元原理:

1. 异质计算要分开优化

不同计算特征的阶段,用不同的硬件/配置。这和广告漏斗一样——召回层用倒排索引(IO 密集),精排层用 GPU 跑模型(计算密集)。

2. 队列分离避免 Head-of-Line Blocking

一个慢任务堵住整个队列。PD 分离本质上是拆队列——快队列和慢队列分开,互不影响。

3. 资源利用率 = 系统吞吐的天花板

混合部署的 GPU 利用率可能只有 30%,PD 分离后可以做到 70%+。这和你的索引压缩项目节省 1750 台机器一样——利用率提升就是成本下降


元结构映射

广告检索系统                      LLM 推理
────────                        ──────
倒排检索 (IO 密集)      →      Prefill (计算密集)
精排打分 (计算密集)      →      Decode (IO 密集)
触发匹配 → 召回集群      →      Prefill 实例
粗排+精排 → 排序集群     →      Decode 实例
动态截断策略             →      KV Cache 管理
L1/L2/L3 数据分层       →      显存层次 (HBM/SRAM)
请求批处理 → 合并打分    →      Continuous Batching
漏斗逐层过滤             →      PD 两阶段流水线

关联我的经验

我在广告系统做了十年的漏斗优化,PD 分离让我感到非常熟悉:

  1. 召回和精排的物理隔离:2018 年我们把召回和精排拆成独立集群,延迟直接降了 50%。PD 分离是同一个思路在推理领域的应用。

  2. 动态资源分配:广告系统的机器配比根据时间动态调整(晚高峰多给召回、凌晨多给线下训练)。PD 分离的 “几 P 几 D” 完全一样——根据流量特征动态调整配比。

  3. 性能模型 = 预估 + 实测:广告系统优化第一步是建立延迟模型(这个模块吃多少 ms),推理优化也一样——先用 roofline model 理论分析瓶颈,再实测验证。

  4. 客户沟通语言:向芯片客户解释 PD 分离的价值——“让你的卡在 Prefill 阶段算力利用率从 30% 提升到 80%,等效于用更少的卡跑更多的 token”。这和告诉广告主“智能出价让你的 ROI 从 2 提升到 3”是同一种思维。


一句话总结本质

PD 分离就是把广告检索的召回/排序分离搬到了大模型推理:不同阶段不同瓶颈,物理隔离各司其职,动态配比随需而变。