AI 技术
#LLM推理#PD分离#KV Cache#吞吐优化#在线服务

Prefill-Decode 分离:为何将长提示词计算与生成计算拆分到不同实例能提升在线服务吞吐

在线大模型服务中,预填充与解码阶段在资源需求上差异显著,混合部署常导致GPU利用率失衡与延迟不稳定。本文以企业知识库问答为场景,解析PD分离架构如何将两阶段分配到不同实例,消除相互干扰,并讨论KV Cache传输、调度策略、适用边界及与未分离方案的权衡。

在线大模型服务中,一个典型的请求会经历两个计算特征截然不同的阶段:先对用户输入的完整提示词做一次前向计算,称为预填充(Prefill);随后逐 token 生成回复,每一步只处理上一个 token,称为解码(Decode)。在传统推理系统中,这两个阶段被放在同一批 GPU 上混合执行,调度器把不同请求的预填充和解码计算打包进同一个批次。这种做法的直接后果是:预填充阶段的大规模矩阵乘法占满算力,而解码阶段每次只做少量计算却要频繁读取不断增长的 KV Cache,GPU 的算力利用率很低。更麻烦的是,一个请求的预填充可能阻塞另一个请求的解码,导致首 token 延迟和单 token 延迟都变得不可预测。

以企业知识库问答为例:用户提交一段 2000 token 的检索结果作为上下文,模型需要先处理这 2000 token 才能生成第一个回复词,随后再逐词输出 300 token 的答案。预填充阶段算力吃紧,解码阶段则被显存带宽卡住。如果这两个阶段共用同一批 GPU,调度器就不得不在“让预填充尽快完成”和“让解码稳定输出”之间反复权衡,最终往往牺牲一方。Prefill-Decode 分离(PD Disaggregation)正是针对这一矛盾提出的架构思路:把预填充和解码分配到不同的 GPU 实例上,让预填充实例专门处理长提示词计算,解码实例专门负责自回归生成,两者通过高速网络传递必要的状态。

本文将以这个知识库问答场景贯穿全文,先分析混合部署为什么低效,再拆解 PD 分离的架构组件、KV Cache 传输与调度策略,最后讨论它在什么条件下收益最大、在哪些场景下可能失效,并与未分离方案做定量与定性对比。

混合部署的瓶颈:两阶段资源需求的结构性冲突

预填充阶段处理整个输入序列,计算量随提示词长度线性增长,表现为一批大矩阵乘法(GEMM),属于计算密集型负载。解码阶段每步只输入一个 token,但需要读取此前所有 token 对应的 KV Cache,计算量小、访存频繁,属于访存密集型负载。这两类负载对硬件资源的要求完全不同:预填充需要高算力,解码需要高显存带宽和足够的 KV Cache 容量。

当它们被混合调度到同一批 GPU 上时,冲突体现在三个层面。第一,算力利用失衡:解码阶段的矩阵规模小,无法填满 GPU 的并行计算单元,而预填充阶段的大算子又容易独占算力,导致整体 GPU 利用率“看起来不低,但有效产出很低”。第二,延迟相互干扰:一个长提示词的预填充可能占用 GPU 数十毫秒甚至更久,期间所有等待解码的请求都被阻塞,直接推高尾延迟。第三,资源调配被耦合:预填充和解码只能按相同比例扩容,无法根据业务负载特征独立调整。例如知识库问答场景中,如果检索结果普遍很长,预填充压力大;如果用户追问频繁,解码占比高。混合部署时,无论哪种情况,都只能用同一批机器硬扛。

Splitwise 论文(Patel 等,2023)通过大量特征分析指出,解码阶段并不需要最新 GPU 的算力,可以用更低功耗、更低成本的硬件运行;而预填充阶段则需要高算力。这一观察直接支持了“把两阶段拆开、分别匹配硬件”的思路。DistServe 论文(Zhong 等,2024)则进一步指出,混合部署不仅造成相互干扰,还使得预填充和解码的资源分配与并行策略被强行绑定,无法为每个阶段单独优化。

PD 分离架构:从逻辑拆分到物理隔离

PD 分离的核心不是修改模型结构或参数,而是把推理执行路径拆成两段:预填充实例(P 实例)接收完整提示词,完成前向计算并生成第一个输出 token,同时构建好该序列的 KV Cache;随后将 KV Cache 和第一个 token 一起传给解码实例(D 实例),D 实例从第二个 token 开始逐词生成,直到遇到结束符。

在工程实现上,PD 分离有三种常见形态,复杂度递增。第一种是调度级解耦(软分离):预填充和解码仍共享同一批 GPU,但调度器对两类请求区别对待,例如给解码请求更高优先级,或限制预填充的 batch 大小。这种方式改动小,但无法彻底消除资源竞争。第二种是资源级解耦:预填充和解码使用不同的 GPU 资源池,预填充池偏向高算力卡,解码池偏向高带宽卡。第三种是服务级解耦:预填充和解码成为独立部署的服务,中间通过 KV Cache 传输或状态句柄连接,各自独立伸缩和调度。

知识库问答场景中,若采用服务级解耦,一次请求的完整流程可以描述为:用户提交查询,系统检索出相关文档片段拼接成提示词,发送给 P 服务;P 服务完成预填充后,将 KV Cache 序列化并通过集群内部网络传给 D 服务;D 服务加载 KV Cache,开始逐 token 生成,最终把完整答案返回给用户。下图展示了这一流程中数据与状态的流动:

flowchart TD
    A[用户请求] --> B[检索与提示词拼接]
    B --> C[P 实例: 预填充]
    C --> D[生成首个 token 与 KV Cache]
    D --> E[KV Cache 传输]
    E --> F[D 实例: 解码]
    F --> G[逐 token 生成]
    G --> H{是否生成结束?}
    H -- 否 --> F
    H -- 是 --> I[返回完整答案]

图中关键转折点在于 KV Cache 传输:预填充完成后,P 实例必须把该请求的 KV Cache 完整交给 D 实例,否则 D 实例无法继续生成。传输效率直接决定 PD 分离的额外开销,也是架构设计中必须优先处理的问题。

KV Cache 传输:PD 分离的通信瓶颈

KV Cache 是预填充阶段产生的中间状态,本质上是每一层注意力机制中 key 和 value 的缓存,大小与序列长度、层数、注意力头数及精度相关。对于 2000 token 的提示词,KV Cache 可能占据数十 MB 甚至上百 MB 显存。在 PD 分离中,这份数据必须从 P 实例移动到 D 实例,传输延迟会直接叠加到请求的总延迟上。

Splitwise 论文的实验表明,利用现代 GPU 集群中的高速背板互联(如 NVLink 或 InfiniBand),KV Cache 传输可以在极短时间内完成,相对于动辄数秒的生成时间可以忽略。但前提是集群拓扑和传输协议经过专门优化。DistServe 论文则强调,预填充和解码实例的放置位置应根据集群带宽决定,以最小化通信开销。

工程上,KV Cache 传输通常有两种实现方式。一种是直接传输:P 实例将 KV Cache 从显存拷贝到 CPU 内存,再通过 RDMA 或 TCP 发送到 D 实例的显存。这种方式简单直接,但涉及多次内存拷贝,延迟较高。另一种是共享内存或池化存储:将 KV Cache 写入一个分布式缓存池(如 Mooncake 论文中提到的 CPU、DRAM、SSD 分层缓存),D 实例按需读取。这种方式减少了直接传输的等待,但引入了额外的缓存管理复杂度。

Mooncake 论文(Qin 等,2024)展示了另一种思路:它把 KV Cache 视为核心资源,不仅将预填充和解码集群分离,还利用 GPU 集群中闲置的 CPU、DRAM 和 SSD 构建了分层的 KV Cache 池。调度器以 KV Cache 为中心,在满足延迟 SLO 的前提下最大化整体有效吞吐。这种设计在长上下文场景中尤其有效,因为长上下文的 KV Cache 更大,直接传输的成本更高,缓存复用能显著减少重复预填充。

调度策略:独立扩缩与 SLO 感知

PD 分离后,预填充和解码成为两个独立的资源池,调度器可以为每个池设计不同的批处理策略。预填充阶段对延迟相对容忍,适合大 batch 处理,以最大化吞吐;解码阶段对延迟极其敏感,batch 过大会导致单 token 延迟上升,因此需要更精细的调度。

DistServe 论文提出了一个关键观点:在线 LLM 应用通常对两个阶段有不同的延迟要求——预填充对应首 token 延迟(TTFT),解码对应单 token 延迟(TPOT)。混合部署时,系统必须在两者之间取舍,或者过度配置资源来同时满足。PD 分离后,可以为预填充和解码分别设置 SLO,并独立优化资源分配和并行策略。例如,知识库问答场景中,用户通常希望首 token 尽快出现(TTFT < 1 秒),但后续生成速度可以稍慢(TPOT < 50 毫秒)。在 PD 分离架构下,可以给 P 池配置更多算力型 GPU 以压缩 TTFT,给 D 池配置高带宽 GPU 以保证 TPOT。

Mooncake 论文还引入了基于预测的早期拒绝策略:当系统过载时,与其让所有请求都排队等待导致 SLO 大面积违反,不如预测哪些请求无法在期限内完成,并提前拒绝它们。这种策略在传统假设“所有请求都会被处理”的系统中是不存在的,但在真实高负载场景中,主动拒绝反而能保护大多数请求的延迟。

调度器还需要决定何时将请求从 P 池转移到 D 池。一种常见策略是“生成第一个 token 后立即转移”,因为第一个 token 是预填充完成的标志。但也可以选择在预填充阶段生成多个 token(称为“预填充-解码重叠”),以减少转移次数,但这会增加 P 实例的负担。实际系统中,转移时机通常与 KV Cache 大小、网络带宽和 D 池的负载相关。

对比未分离方案:延迟与吞吐的权衡

为了评估 PD 分离的实际收益,需要与传统的混合部署方案进行对比。混合部署的典型代表是 vLLM 等系统采用的 continuous batching,它允许预填充和解码请求在同一批次中交错执行,以提高 GPU 利用率。然而,这种方式无法消除两阶段之间的资源竞争。

下表从多个维度对比了 PD 分离与混合部署的差异,基于论文中的定性结论和典型工程经验,不包含具体性能数字。

维度混合部署(未分离)PD 分离
资源利用预填充大算子与解码小算子争抢算力,GPU 算力利用率低预填充池专注算力,解码池专注带宽,各得其所
延迟稳定性预填充可能阻塞解码,尾延迟高两阶段隔离,解码延迟稳定
扩缩容灵活性两阶段绑定,只能同比例扩容可独立扩缩,按负载特征调整
硬件选择必须使用同一类型 GPU可为预填充选高算力卡,为解码选高带宽卡
实现复杂度低,单集群即可高,需要网络传输和状态管理
适用场景短提示词、低并发、对延迟不敏感长提示词、高并发、严格 SLO

Splitwise 论文报告,在相同成本下,PD 分离可将吞吐提升 1.4 倍,成本降低 20%;或者在相同成本和功耗预算下,吞吐提升 2.35 倍。DistServe 论文则显示,在满足 TTFT 和 TPOT 约束的前提下,PD 分离可以服务 7.4 倍更多的请求,或在相同请求率下将 SLO 收紧 12.6 倍。Mooncake 论文报告,在模拟的长上下文场景中,相比基线方法吞吐提升最高达 525%,在真实负载下帮助 Kimi 处理了 75% 更多的请求。这些数字来自各自论文的实验设置,不能直接横向比较,但都指向同一个结论:当两阶段资源需求差异显著时,PD 分离能带来数量级的吞吐改善。

需要强调的是,这些收益并非没有代价。PD 分离引入了额外的网络通信和状态管理,如果集群带宽不足或 KV Cache 传输优化不佳,收益可能被抵消。此外,PD 分离的收益与提示词长度和生成长度之比有关:如果提示词很短、生成很长,预填充压力小,分离的意义就减弱;反之,如果提示词极长,KV Cache 传输成本可能成为新瓶颈。

适用边界与失败模式

PD 分离并非万能,它在以下条件下收益最大:提示词较长(例如检索增强生成或代码补全场景),并发请求量高,且应用对 TTFT 和 TPOT 有明确 SLO。在这些场景中,预填充和解码的资源需求差异被放大,混合部署的冲突也更严重。

然而,PD 分离也存在一些天然缺陷和失败模式。首先,KV Cache 传输增加了请求的临界路径延迟,如果网络带宽不足或传输协议低效,TTFT 可能反而变差。其次,预填充和解码池的负载可能不均衡:如果业务突发大量短请求,预填充池可能空闲,而解码池过载;反之亦然。这要求调度器具备跨池的负载均衡能力,甚至需要动态调整池的大小,而这在物理分离的集群中并不容易。

另一个问题是长上下文场景下的 KV Cache 复用。Mooncake 论文指出,长上下文场景中,不同请求可能共享相同的前缀(例如系统提示词或检索到的公共文档)。如果这些前缀的 KV Cache 能被缓存和复用,就可以避免重复预填充,大幅提升吞吐。但这也要求调度器能够识别和匹配共享前缀,并管理缓存的一致性。

此外,PD 分离增加了系统的故障域。如果 D 实例宕机,正在生成的请求会中断,需要重新从预填充阶段开始或从检查点恢复。这要求系统具备容错机制,例如 KV Cache 的持久化或复制。在 Mooncake 的架构中,KV Cache 池化存储天然支持一定程度的容错,但代价是额外的存储开销。

最后,PD 分离对模型并行策略也有影响。预填充和解码可能需要不同的张量并行度或流水线并行度,因为两者的计算和内存特征不同。DistServe 论文专门讨论了如何为每个阶段独立优化并行策略,但这增加了部署的复杂性。

可观测性与调优方向

在生产环境中部署 PD 分离系统,需要监控一系列关键指标来验证效果和定位问题。

  • 预填充阶段的指标:平均和 P99 的 TTFT、预填充吞吐(token/s)、GPU 算力利用率、batch 大小。
  • 解码阶段的指标:平均和 P99 的 TPOT、解码吞吐(token/s)、显存带宽利用率、KV Cache 命中率。
  • 传输指标:KV Cache 传输延迟、传输带宽、失败重试率。
  • 端到端指标:请求成功率、SLO 违反率、整体吞吐(请求/s 或 token/s)。

当出现性能问题时,可以按以下路径定位:如果 TTFT 升高,检查 P 池负载和算力利用率,可能需要增加 P 实例或优化预填充 batch;如果 TPOT 升高,检查 D 池的显存带宽和 KV Cache 容量,可能需要减少 batch 或增加 D 实例;如果端到端延迟中传输占比过高,则需要优化 KV Cache 压缩或改用更快的互联。

调优方向包括:调整预填充和解码池的比例,根据业务负载特征动态伸缩;优化 KV Cache 传输协议,例如使用 RDMA 或 GPUDirect;实现 KV Cache 复用,利用前缀缓存减少重复预填充;设计更智能的调度策略,如基于预测的早期拒绝或负载感知的请求路由。

尚未解决的问题

尽管 PD 分离已被多家大型服务采用,但仍有一些开放问题。首先,如何自动决定预填充和解码池的最优比例,以及何时进行动态调整,目前多依赖人工经验和离线仿真。其次,KV Cache 的压缩和量化传输仍处于研究阶段,如何在减少传输量的同时不损失生成质量,尚无统一答案。再次,PD 分离与模型并行(如张量并行、流水线并行)的联合优化仍缺乏系统性方案。最后,当模型规模进一步增大、上下文长度达到百万 token 时,KV Cache 的大小将变得极其庞大,传输和存储将成为新的瓶颈,可能需要更根本的架构变革。

PD 分离的价值在于它承认了预填充和解码是两类不同的工作负载,并据此重新设计了推理系统的资源分配方式。对于长上下文、高并发的在线服务,它提供了一条在不牺牲延迟的前提下提升吞吐的可行路径。但它的成功依赖于高速网络、精细调度和灵活的资源配置,并非所有场景都值得引入。理解它的原理和边界,有助于在实际系统中做出合理的架构决策。

资料来源

  1. Splitwise: Efficient generative LLM inference using phase splitting
  2. DistServe: Disaggregating prefill and decoding for goodput-optimized large language model serving
  3. Mooncake: A KVCache-centric Disaggregated Architecture for LLM Serving
  4. 大语言模型(LLM)推理加速:预填充(Prefill)和解码(Decode)解耦(PD 分离) | Wilson Wu