LLM 推理为何应分离 Prefill 与 Decode
技术长文论证:在负载充足时,分离部署 Prefill 与 Decode 几乎总是优于聚合方案,并给出速率平衡公式与三项前…
在大规模 LLM 在线推理场景中,Prefill(一次性处理整段 prompt)与 Decode(逐 token 生成)具有截然不同的资源特征:前者计算密集、显存压力小,后者显存密集、计算压力小。把这两类任务放在同一组 GPU 上调度,常常顾此失彼。本文作者主张,只要负载足够大、工程实现足够细致,分离部署(Disaggregated Inference)几乎总是更优选择。
为什么要把 Prefill 和 Decode 切开
最早提出这一思路的工作包括 DistServe 与 Splitwise:Prefill 在一组 GPU 上完成,把产出的 KV Cache 经网络传给另一组 Decode GPU,再逐 token 使用。之所以能这样切,是因为 Prefill 在请求级别一次性产出 KV Cache,Decode 再按 token 顺序消费,二者天然解耦。
传统上,人们把分离部署当成调 TTFT(首 token 延迟)与 TPOT(每输出 token 延迟)的工具。作者认为它远比这更强——它能让两类 SLO 完全互不干扰。
现有替代方案的局限
聚合部署通常有两种做法:
- 时间切分(Temporal Disaggregation):先 Prefill 一批请求,再 Decode,必要时停下 Decode 去 Prefill 新请求。这种方式会拉高 TPOT 的长尾分位数,对延迟敏感业务不友好。
- 分块 Prefill(Chunked Prefill,来自 SARATHI):在同一个 GPU 批里同时混跑 Decode 请求与 Prefill 的若干 token 块。其理想收益是"Prefill 与 Decode 互相白嫖对方的多余资源",但实践中并不理想——一段 Prefill 被切成 N 块就意味着 KV Cache 要在显存里搬运 N 次,N 越大 TPOT 越好、TTFT 越糟,调度难度陡增。
后续工作如 Bullet、DuetServe 以及 CUDA Green Contexts 尝试用 SM 掩码等方式在同一 GPU 上做更细粒度的资源划分,但本质仍是把两种"工种"塞进同一台机器。
如何做速率平衡
分离部署的代价只剩一条:Prefill 节点产出的 KV Cache 必须搬运到 Decode 节点。换回的收益是 SLO 彼此独立。
设一条请求的 prompt 长度为 ISL,预计输出 OSL(事先未知)。一台专做 Prefill 的 GPU 处理 prompt 速率是 r_P,则该请求 Prefill 耗时:
- t_P = ISL / r_P
Decode 端每步处理整批 B 条序列,每生成一个 token 单条请求分摊到的 GPU 时间为 t_step / B,整条请求 Decode 耗时:
- t_D = OSL · t_step / B
当请求以 R 条/秒的速率进入稳态时,Prefill 池每秒需提供 R·t_P GPU·秒,Decode 池需提供 R·t_D GPU·秒。总 GPU 数为 N 时,平衡的拆分比例为:
- φ = t_P / (t_P + t_D) = B·ISL / (B·ISL + r_P·t_step·OSL)
φ 由流量画像(ISL、OSL)与两端处理能力(B、r_P、t_step)共同决定。
分离部署真正"稳赢"的三个前提
流量画像会随时间漂移。要让分离部署永远不输聚合部署,必须同时满足:
- 整机数足够多:分配到两端的工作节点在取整后仍有足够粒度,避免出现"Prefill 池只分到 0 台 GPU"的窘境。
- 网络够快:KV Cache 从 Prefill 到 Decode 的传输带宽必须跟得上 Prefill 的产出速率,否则 Decode 池会空转。
- 流量可追踪:ISL/OSL 画像基本稳定,或者通过路由让各池看到的画像基本稳定,或者池间能比画像变化更快地重新平衡。
三项同时成立时,分离部署稳态不劣于聚合部署;而在大多数有意义的在线服务规模上,它还显著更优。
