最近在理解 P/D 分离(Prefill/Decode Disaggregation),核心问题是它到底适合什么时候用。大模型推理中真正昂贵的是反复计算可复用的中间状态,这篇笔记就是我一路把问题从 KV Cache、P/D 分离、硬件组合、网络成本,最后推导到业务形态(Workload)和基准测试(Benchmark),以此来回答对于一般推理服务而言“什么时候值得用”的思考过程。

从生成过程到 KV Cache

要理解 P/D 分离,得先退回到大模型推理的最基本原理。

大模型生成文字是一个字一个字往外蹦的。每生成一个新字,它都必须回头看一遍前面所有的字,才能决定下一个字该说什么。如果每次都把前面的字重新算一遍,计算量会大到离谱。为了省事,推理引擎会把前面已经算过的中间状态(也就是 Transformer 里的 Key 和 Value 矩阵)存下来。这个存下来的中间状态,就是 KV Cache。

有了这个概念,大模型的推理就可以明确划分为两个阶段: 第一阶段是读懂用户的输入(Prompt),把这些输入一次性算完并存进 KV Cache 里,这个阶段叫 Prefill。 第二阶段是基于存好的 KV Cache,一个字一个字地生成回复,这个阶段叫 Decode

Prefill Decode 分离什么时候用的判断框架

在长上下文时代,问题出现了。读完几万字的 prompt 并生成 KV Cache(Prefill)非常昂贵。而单台机器的显存是有限的,如果 KV Cache 存满了,新的请求进来,或者同一个文档被另一个用户提问,系统就不得不把之前算好的 KV Cache 扔掉,重新做一遍昂贵的 Prefill。

这就引出了一个很核心的概念:P/D 分离(Prefill/Decode Disaggregation)

把 KV Cache 当成一种可以跨机器调度的系统资源,把整个架构拆成了几个核心组件:专门负责处理 prompt 生成 KV Cache 的 Prefill 池,专门负责基于 KV Cache 持续生成 token 的 Decode 池。这里真正要拆开的,不只是两个服务进程,而是两个硬件瓶颈完全不同的阶段。

其实业界有很多同类方案在探索这个方向。比如 Mooncake、vLLM、SGLang、LMCache、Dynamo 等都在不同层面处理 KV cache 或者 P/D 分离问题。有的偏向单实例内部的前缀复用,有的做运行时的分层缓存,也有的直接把分布式存储、低拷贝传输、缓存感知调度和过载拒绝全部揉进了一个生产级架构里。

Prefill 和 Decode 到底在抢什么资源?

理解了为什么要拆分之后,真正要拆开的其实是一个更底层的问题:Prefill 和 Decode 到底在抢什么资源?

搞清楚这个物理机制,是理解后续所有优化的前提。

Prefill 阶段的任务是读完整个 prompt,算出第一个输出 token 之前的一切。 假设你的 prompt 有 1000 个 token,Prefill 会一次性把这 1000 个 token 并行处理完,算出每一层的 hidden states、Q/K/V 和 MLP 输出,然后把每个 token 的 Key 和 Value 存进 KV cache 里。最后基于 prompt 最后一个位置算出第一个输出 token 的 logits。这个过程非常吃计算力,它就像是大矩阵乘大矩阵,只要 prompt 够长,GPU 的算力就能被充分压榨。首字返回时间(TTFT)基本就是由 Prefill 决定的。

Decode 阶段则是基于已经算好的 KV cache,一个 token 一个 token 地生成。 每一步 Decode 其实只输入刚生成的那一个 token,但它必须把历史所有 token 的 KV cache 都读一遍。这个过程的计算规模很小,更像是小 batch 或者矩阵和向量相乘,GPU 的算力根本吃不满,瓶颈全卡在 HBM 和显存带宽上。

如果把这两个阶段混在一张卡上跑,问题就来了。

在线流式输出的时候,Decode 想要顺畅、短步频地生成 token。但 Prefill 想要大块算力、长时间占用 GPU。如果一个 batch 里混进了一个长 prompt 的 Prefill 任务,Decode 的下一个 token 就必须等这个长长的 Prefill kernel 算完才能返回。 结果就是,正在看流式输出的用户会觉得文字卡顿了。

Prefill 与 Decode 争抢 GPU 资源的冲突示意图

如果调度器优先照顾 Decode,流式输出更顺畅了,但新进来的请求就得排队等 Prefill,首字返回时间(TTFT)就会受到严重影响。DistServe 把这类问题精确地概括为 Prefill/Decode 资源和并行度耦合。vLLM 里的 chunked prefill 机制其实也是在做这种取舍:把长的 Prefill 切碎,优先保证 Decode 的流畅度,但这往往会牺牲一点 TTFT。

既然瓶颈不同,能不能用异构硬件?

既然这两者的物理瓶颈完全不同,一个很自然的想法就冒出来了:我们是不是可以组装一个异构的推理系统,用高计算低带宽的卡做 Prefill,用高带宽低计算的卡做 Decode?

我一开始想到了苹果的 M5 芯片,以为它的统一内存很适合做 Decode。但很快发现这个判断不准:基础款 M5 的内存带宽并不高,哪怕是 M5 Max,带宽也远低于 H100、H200 这种数据中心卡。苹果统一内存的优势是容量大和 CPU/GPU 共享,并不等于拥有 HBM 级别的极高带宽。

真正符合“高计算、低带宽”画像的是类似英伟达 DGX Spark 这样的机器。它的官方规格是 1 PFLOP FP4 算力,配上 128GB 的统一内存,但带宽只有 273GB/s。这种高计算带宽比(compute-to-bandwidth ratio)的硬件更适合 Prefill,如果拿去做 Decode,很容易被带宽卡住。

异构硬件架构中的 Prefill 与 Decode 节点互补示意图

P/D 分离的成本模型

顺着异构硬件的思路往下走,我们会发现,P/D 分离不仅仅是一种部署拓扑,它本质上是一个决定什么时候值得用的成本模型。

我们可以建立一个简单的成本分解模型: 单次请求总成本 = Prefill 成本 + Decode 成本 + KV 传输成本 + 调度与空闲损耗。

如果异构系统能把前两项(计算成本)降下来,且后两项(传输和调度损耗)的上升幅度没有把收益抵消,整体的 token 性价比就会大幅提升,此时分离就是有价值的。

P/D 分离架构的成本与开销天平模型

这种架构在特定场景下非常值得用:比如长上下文、长会话、Agent 循环调用、RAG,以及任何高前缀命中率的场景。在这些场景里,Prefill 的计算量巨大,KV Cache 的复用率极高,拆分开来独立优化的收益非常明显。

反过来,如果是短 prompt 的普通聊天,Prefill 本身就不怎么耗时,这时候把 P 和 D 拆开,反而会因为增加了网络传输和调度开销,导致得不偿失,分离就不适合使用。

硬件组合:如何搭配才能体现分离的价值?

硬件画像清晰之后,问题就变成了:如果手里有 H20、H200、RTX 5000 甚至 DGX Spark,到底该怎么搭配?

这里的判断标准很明确:Prefill 侧优先看算力价格比、长 prompt 并行效率和显存能否放下模型;Decode 侧看重显存容量、显存带宽、KV cache 容量和可预测低延迟。

这里举两个比较有代表性的异构组合例子:

DGX Spark 做 Prefill,H20 做 Decode。 这是一个非常典型的互补组合。Spark 算力强适合啃长 prompt,H20 显存大带宽高适合长时间 Decode。这个方案很适合多轮 Agent、RAG 这种长上下文、预算敏感的实验场景。

但这个方案的风险在于中间的 KV 传输。如果两边节点之间的网络只有普通的 200Gbps,网络带宽可能会成为新的瓶颈。在实际的 P/D 分离部署中,网络层的选择非常关键。通常会考虑 100/200/400 甚至 800Gbps 的以太网(配合 RoCE/RDMA),或者 InfiniBand/RDMA。如果在同一个紧耦合的 GPU 节点内,则会依赖 NVLink/NVSwitch。同时还需要配合像 Mooncake Transfer Engine 或者 NIXL 这样的高性能传输库。这些高速网卡、交换机、线缆光模块以及运维复杂度,都会成为总成本中不可忽视的一部分。

通过高速网络连接的 P/D 异构 GPU 集群拓扑图

RTX PRO 5000 Blackwell 做 Prefill,H20 做 Decode。 这更像是一个生产环境的性价比方案。RTX PRO 5000 提供了 48/72GB GDDR7 显存、1.344TB/s 带宽和不错的 FP4 算力,做 Prefill 成本低,把重头戏 Decode 交给 HBM 带宽极高的 H20。

当然,如果预算充足,全栈使用 H200 依然是一个性能极强的同构基线。H200 的 HBM3e 容量和带宽都很顶,既能做强 Prefill 也能做强 Decode,只是在纯粹的 token 成本性价比上,可能不如精细调配的异构方案。

硬件之外,业务形态才是决定性因素

本来以为硬件搭配清楚了,P/D 分离的逻辑就闭环了。但再往深处想一层就会发现,脱离了具体的请求形态(Workload Pattern)去谈硬件,结论会依据不足。

前面提到 P/D 分离本质上是在做资源重新分配,而请求形态会直接改变各项成本的比例。

如果业务是短输入、长输出,那 Decode 的耗时会占绝对主导。如果业务是长输入、短输出,那 Prefill 就是大头。

当前流行的 Agent,以及像“小龙虾”这样的长上下文应用,很多都是典型的长输入、短输出形态。它们通常携带着极长的系统 prompt、工具定义(tool schemas)、历史记忆、检索到的文档,或者复杂的任务状态。但模型最终给出的回答可能非常短,比如一个决策、一次工具调用、一句简短的指令,或者一个简单的回复。在这种形态下,Prefill 的压力极大,而 KV Cache 的复用变得尤为重要。

而且,prompt 的物理长度不等于真实的 Prefill 工作量,关键要看前缀复用率。 10 万 token 的全新 prompt,和 9.5 万 token 已经命中缓存、只有 5000 个新 token 的 prompt,对算力的要求天差地别。在上述的高复用场景中,P/D 分离和全局 KV cache 管理架构真正能发挥出巨大的价值。

长输入与短输入两种业务形态的工作流耗时对比图

此外,请求长度往往呈现长尾分布(heavy-tail)。偶尔出现的一个超长 Prefill 会制造严重的 TTFT 尾延迟,而一个超长 Decode 会长期霸占 slot,拖慢其他请求的 TPOT。不同的业务对 SLO 的要求也完全不同:实时聊天看重 TTFT 和 TPOT,长文总结只看总完成时间,而 Agent 循环可能更看重 TTFT、缓存复用和整体可靠性。

为什么批处理标注通常不适合用 P/D 分离?

顺着这个逻辑反向思考一下:如果是不要求流式输出的批处理标注任务,P/D 分离什么时候还值得用?

答案是:收益可能远不如直接用大 batch 同构吞吐。

因为目标函数变了。 在线聊天关心的是首字要快,后续生成要顺畅,因为用户正盯着屏幕等。但批处理标注通常只关心每小时能处理多少条数据,每百万 token 的成本是多少,以及任务的总完成时间。

在离线批处理时,我们完全可以把请求排队、重排,按 prompt 长度分桶,凑成巨大的 batch 直接把 GPU 算力吃满。虽然物理机制上,Decode 依然会被同一个 batch 里的长 Prefill 阻塞,但离线任务根本不在乎某个 token 是不是晚了几秒钟出来,只要总吞吐高就行。同构批处理还可以做很多离线优化,比如限制最大输出长度、把前缀相同的任务强行凑在一起跑。

离线批处理任务的大 Batch 同构吞吐示意图

P/D 分离是有固定成本的。Prefill 节点算完 KV,要跨网络传给 Decode 节点,Decode 节点要接收并重建状态,调度器还要维护两边的 slot,甚至可能还需要远端的 KV store。如果放弃了 P/D 分离最核心的“延迟隔离”收益,又没有极端的异构硬件成本优势,同构大 batch 显然是更简单高效的选择。

最后的工程决策:先评估,再动架构

到这里,P/D 分离在我脑子里才算变成了一个完整的工程问题。

以前看到新技术,总觉得架构更先进就应该跟进。但现在我意识到,P/D 分离并不会天然更优,它解决的是特定硬件和特定请求形态下的资源错配。

它的代价是系统复杂度会直线上升。路由怎么选 P/D 节点?Prefill 节点挂了请求怎么重试?Decode 节点挂了流式请求怎么接管?扩缩容的时候流量怎么平滑转移(drain)?KV cache 怎么在节点间迁移、复制和淘汰?请求状态、session 和前缀元数据怎么保持一致?模型升级时 KV cache 兼不兼容?网络抖动时怎么限流降级?这些分布式系统的经典难题,都会在推理集群里重新出现。

所以,更审慎的评估方式,是先把 workload、硬件和网络三件事分开看。

第一类问题是 workload。 这里要同时看输入和输出的分布,也要看有多少输入可以复用。明确业务对 TTFT 和 TPOT 的容忍度,评估请求是否可以排队、重排或者 batch 化。

第二类问题是硬件和网络。 只有当 Prefill 侧和 Decode 侧确实存在资源错配时,拆分才有意义。评估是否有高算力低带宽的卡适合做 P,是否有高带宽大显存的卡适合做 D,以及网络互联条件是否足够支撑庞大的 KV 传输。

第三类问题是实际的基准测试(Benchmark)。 在决定重构之前,需要进行小规模的测试对比。跑一下单机同构的基线,跑一下无 KV 复用的 P/D 分离,再跑一下带前缀复用的 P/D 分离。

在测试时,不要只看平均 tokens/sec,要看 TTFT 和 TPOT 的 P50/P95/P99 延迟,看满足 SLO 的有效吞吐(goodput),还要关注 GPU 利用率、显存占用、网络带宽、KV 传输时间以及两边的队列积压情况。

只有当 benchmark 显示有效吞吐有 30% 到 50% 的明显提升,或者在同等延迟要求下成本大幅下降,且 KV 传输和调度开销完全可控时,才值得真正去碰 P/D 分离集群化的复杂设计。

P/D 分离工程落地评估的三阶段决策树

很多技术探索走到最后,都会回归到一个核心判断:什么时候分离带来的收益能覆盖它的复杂性。

我现在越来越觉得,判断 P/D 分离什么时候用,不取决于它听起来有多先进,而取决于它有没有真正改善当前业务形态(Workload)的成本结构与运行效率。

如果你也在做长上下文、Agent 或者 RAG 推理服务,我会很想知道:你们现在最大的瓶颈,到底是在 Prefill、Decode、KV cache,还是网络和调度?

图片

欢迎关注微软 智汇AI 官方账号

一手资讯抢先了解

图片

喜欢就点击一下 在看 吧~

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐