预填充-解码分离
预填充-解码分离(prefill-decode,PD)也称为分离式推理(disaggregated inference),是一种在独立硬件资源上运行 LLM 推理两个主要阶段(预填充与解码)的服务架构。"分离式预填充"和"分离式服务"往往指同一个核心思想:为每个阶段分配专用的资源,以满足其不同的计算和内存需求。
将预填充与解码放在一起的问题
要理解为什么共置会产生问题,先简单回顾一下 LLM 推理是如何工作的,它分两步:
- 预填充(prefill):并行处理整个序列,并将注意力层的键向量和值向量存储在 KV 缓存中。由于它使用大型矩阵运算一次性处理所有 token,预填充受计算限制,但对 GPU 内存的要求并不高。
- 解码(decode):通过复用之前构建的 KV 缓存,逐个生成输出 token。每个生成的 token 都需要反复加载模型权重并访问不断增长的 KV 缓存。因此,解码需要快速的内存访问,但计算需求较低。
长期以来,标准的推理方式是让这两个步骤一起运行。表面上这似乎很直接。
实际上,你经常会同时收到多个请求。每个请求都有自己的预填充和解码需求,但同一时间只能运行一个阶段。当 GPU 忙于计算密集的预填充任务时,解码任务必须等待,这会增加 ITL,反之亦然。
由于预填充主要决定 TTFT,解码影响 ITL,将它们共置会使其难以同时优化这两个指标。

将预填充和解码共置导致的延迟增加。图片来源
为什么分离是有意义的
PD 分离的思想很简单:把这两个截然不同的任务分开,让它们互不干扰。下面是一个示例架构:
主要好处包括:
- 专用资源分配:预填充和解码可以在不同硬件上独立调度和扩缩容。例如,如果你的工作负载有大量提示词重叠(如多轮对话或智能体工作流),这意味着你的大部分 KV 缓存可以被复用。结果是预填充的计算需求降低,你可以把更多资源投入到解码上。
- 并行执行:预填充和解码阶段不再相互干扰。你可以更高效地并行运行它们,这意味着更好的并发度和吞吐量。这种分离还可以改善尾部延迟。在共置情况下,一次单独的长预填充会拖慢其后的每一个飞行中的解码请求,从而提高 P95 和 P99 延迟。
- 独立调优:你可以为预填充和解码实施不同的优化技术(如张量并行或流水线并行),以更好地达成你的 TTFT 和 ITL 目标。
一些开源框架和项目已经添加了对 PD 分离的支持,包括 SGLang、vLLM、Dynamo 和 llm-d。
分离并非总是灵丹妙药
尽管 PD 分离听起来很有前景,但它并非一刀切的解决方案。
-
阈值很重要:如果你的工作负载太小,或你的 GPU 配置没有针对这种方法进行调优,性能可能会下降(在我们的测试中下降了 20-30%)。
-
本地预填充可能更快:对于较短的提示词,或者当解码引擎具有较高的前缀缓存命中率时,在解码 worker 上本地运行预填充往往更快、更简单。
-
数据传输成本:分离要求在预填充和解码 worker 之间快速、可靠地移动 KV 缓存。这意味着你的解决方案必须支持快速、低延迟的通信协议,并且这些协议既与硬件无关也与网络无关。除非分离带来的性能提升超过了数据传输成本,否则整体性能实际上可能会下降。供你参考的现有数据传输方法: NVIDIA Inference Xfer Library (NIXL)、CXL、NVMe-oF。
对于生产环境,请考虑以下设计问题:
- 解码 worker 应该直接从预填充 worker 获取 KV 块,还是双方都应该使用共享的缓存层?
- KV 块应该在预填充之后立即移动,还是等到解码真正需要时才惰性移动?
- 路由器如何决定是复用现有缓存、运行本地预填充,还是将请求发送到独立的预填充池?
-
缓存兼容性很重要:预填充 worker 和解码 worker 必须在 KV 布局、页大小、dtype、注意力变体以及任何额外的缓存元数据上保持一致。异构的 KV 类型(例如量化 KV 缓存、VLM 编码器状态和投机解码缓存)会使这种交接比移动一个标准全注意力 KV 张量更加复杂。
跨集群预填充-解码分离
在许多分离式系统中,预填充和解码机器是同一集群内的邻居,通过高速、低延迟的互连相连。
跨集群(或跨数据中心)PD 分离意味着你将工作流拆分,让预填充和解码阶段在完全独立的集群中运行,有时甚至位于不同的数据中心或区域。
为什么要在集群间拆分预填充和解码?
有两个主要驱动因素正推动基础设施走向这种分布式模式:
-
合适芯片用在合适的任务上。预填充计算密集,而解码内存带宽密集。芯片设计正朝着匹配这些不同需求的方向分化:
- NVIDIA Rubin CPX 旨在最大化预填充吞吐量。
- Groq LPU 专为高速解码带宽而设计。
问题在于这些芯片并不总是在同一个地方。它们常常按硬件类型分组部署在独立的集群中。如果你强制预填充和解码待在一起,就无法充分使用每个阶段的最佳硬件。将它们拆分,你可以让长预填充运行在计算优化的机器上,同时将解码保留在带宽优化的机器上。
-
灵活性。在生产环境中,预填充和解码并不会均匀地扩展。流量和提示词长度会变化。前缀缓存命中率会变化。有时预填充成为瓶颈,有时解码成为瓶颈。
如果两个阶段都被锁在同一个集群中,你就被固定在了固定的资源比例上。这可能导致一侧过度配置,另一侧出现瓶颈。将阶段拆分到不同集群,可以让你分别扩展每一侧。
核心问题:KV 缓存的移动
预填充完成后,KV 缓存必须被发送到解码集群。在集群内部,这很便宜。跨集群则可能很昂贵。有两件事让这件事变得棘手:
- KV 缓存可能很大。通过网络传输它可能会抹掉更快预填充带来的任何收益。
- 并非所有请求都能受益。短提示词或缓存命中提示词从远程预填充中获益不多,但你仍然要付出网络成本。
所以,如果你天真地把所有东西都发送到远程预填充集群,性能实际上可能会变差。
预填充即服务
这篇论文 将预填充即服务(Prefill-as-a-Service,PrfaaS)作为一种让这种配置可行的实用方式提出。其思想很简单:不要把所有东西都跨集群发送。要有选择性。
- 将短请求或已缓存的请求留在本地
- 只把长的、未缓存的预填充发送到远程计算集群
这使跨集群 PD 变成了一个路由问题。调度器根据提示词长度(尤其是未缓存的 token)、前缀缓存局部性、预填充队列压力、解码容量和可用网络带宽来决定每个请求的去向。
论文报告,这种选择性方法相对标准 PD 基线取得了显著收益:
- 吞吐量提高 54%
- P90 TTFT 降低 64%
这些收益来自更好的资源利用,而不只是更快的硬件。
何时应该使用跨集群 PD 分离?
这种部署选项在以下情况下效果最好:
- 你的工作负载包含许多长的、未缓存的提示词
- 你有一个理解缓存局部性、排队和带宽的调度器
如果你的大多数请求都很短或以缓存为主,通常把所有东西都放在一个集群里更简单、也更快。