17. Prefill-Decode 分离部署(Disaggregated Serving)的核心思想是什么?

整理 PD 分离部署的动机、机制与工程取舍。

简单回答

Prefill-Decode 分离(PD Disaggregation)是把 Prefill 和 Decode 两个阶段拆到不同的 GPU 实例上跑——一组机器专门做 Prefill,另一组专门做 Decode,请求走完 Prefill 后把生成的 KV Cache 通过高速网络传给 Decode 实例继续生成。动机是 Prefill 是计算密集型、Decode 是访存密集型,两者对硬件的需求和最优 batch 策略完全不同,混在同一台机器上调度互相干扰。分离后每组实例可以独立选择硬件、独立做 batching、独立扩缩容,能进一步提升整体吞吐和 SLA 达成率。代价是 KV Cache 跨机传输带来的开销和工程复杂度。

详细解释

Chunked Prefill 还不够吗

本专题第 16 篇讲的 Chunked Prefill 把 Prefill 拆成小块和 Decode 在同一台机器上混合调度,已经大幅缓解了两者抢资源的问题。为什么还需要 PD 分离?

核心矛盾在 Chunked Prefill 解决不了的部分。Prefill 和 Decode 对硬件的"理想配置"不一样:Prefill 受益于高算力(FLOPS),Decode 受益于高显存带宽和大显存容量(KV Cache 占地方)。同一台机器只能同时优化其中一个。

更关键的是两者对 batch 策略的需求相反。Prefill 的 batch 不能太大——一个 16K Prompt 的 Prefill 已经几乎打满 GPU 算力,再加 batch 收益很小。Decode 反过来——单个请求 Decode 严重浪费算力,必须靠大 batch 才能把 GPU 喂饱。混在一起调度时这两套 batching 策略互相妥协,谁都达不到最优。

PD 分离把这个矛盾彻底拆解:Prefill 实例选一种 batch 策略和硬件配置,Decode 实例选另一种。

工作流程

一个请求的完整路径:

  1. 请求先进入路由层(gateway 或 router)。路由根据请求特征(Prompt 长度、是否命中前缀缓存等)决定送给哪个 Prefill 实例。
  2. Prefill 阶段:选定的 Prefill 实例处理整个 Prompt,生成完整的 KV Cache(一个或多个 chunk 算完)。同时生成第一个 output token 返回给用户(满足 TTFT)。
  3. KV Cache 传输:Prefill 实例把生成的 KV Cache 通过高速网络(NVLink、InfiniBand RDMA)传给一个 Decode 实例。
  4. Decode 阶段:Decode 实例接收 KV Cache,加入自己的 batch 中,开始逐 token 生成 response。
  5. 整个 response 流式返回给用户。

KV Cache 跨机传输是这个架构的核心难点。一个 7B 模型 8K 上下文的 KV Cache 大约几个 GB,要在百毫秒级别传完才能不影响 TTFT。这要求 Prefill 实例和 Decode 实例之间有专用高速网络。

哪些场景受益最大

PD 分离的收益和"长 Prompt + 长 Decode"场景成正相关。

长 Prompt 但 Decode 短(典型:摘要、翻译、分类)—— Prefill 占总时间比例大,Decode 算力浪费严重。分离后 Prefill 用算力强的机器(H100),Decode 用便宜的小算力 GPU(甚至 A30),整体成本下降明显。

长 Decode 但 Prompt 短(典型:开放式对话、文章生成)—— Decode 占主导。分离后 Decode 实例可以做超大 batch(128 甚至更大),Prefill 不抢资源,吞吐量大幅提升。

Prompt 和 Decode 都长(典型:Agent、长文档分析)—— 这是 PD 分离收益最大的场景。两端都重,混合调度严重低效。分离后两边各自达到接近理想吞吐。

反过来 Prompt 和 Decode 都短(典型:简短工具调用、单轮 QA)—— Prefill 和 Decode 各自时间都很短,KV Cache 传输的网络开销可能盖过分离的收益。这种场景不分离反而更好。

工程上的核心难点

KV Cache 传输延迟

KV Cache 大小是 ,L 是层数,H 是 head 数,D 是 head dim,n 是 token 数。对 70B 模型 8K 上下文,KV Cache 约 5-10 GB。即使用 InfiniBand RDMA(200 Gbps = 25 GB/s 实际带宽),传完也要几百毫秒。

减少传输开销的手段:

  • 流式传输:不等整个 Prefill 算完再传,而是每个 chunk 算完就传一段,和后续 chunk 计算重叠。Mooncake、DistServe 等系统都用了这种 pipeline。
  • KV Cache 压缩:传输前做 INT8 或 FP8 量化,传输量减半。Decode 端再反量化。
  • 拓扑感知调度:路由时尽量把请求送到和 Decode 实例物理相邻(同机柜)的 Prefill 实例,缩短传输距离。

调度复杂度

PD 分离把单引擎的"一份调度"拆成"路由 + Prefill 调度 + Decode 调度"三层。路由要根据各 Prefill / Decode 实例的当前负载、KV Cache 状态、预期 Prompt 长度等做决策。Prefill 和 Decode 实例数量不一定相等(典型 Decode 数量更多,因为 Decode 阶段更慢),扩缩容也独立。生产部署比单引擎复杂很多。

前缀缓存(prefix caching)的兼容

如果 Prompt 有共享前缀(典型:System Prompt 一样、Few-shot 示例一样),希望 KV Cache 复用。在单引擎里前缀缓存就在本机,访问极快。PD 分离后前缀缓存要设计在 Prefill 实例上,但请求要 Decode 时还要把对应的 KV Cache 传过去——前缀缓存的命中率就要看路由能否把同前缀的请求路到同一个 Prefill 实例。

真实部署案例

DeepSeek 的推理系统(公开过部分细节)就是 PD 分离架构。Prefill 实例和 Decode 实例分别用不同的硬件配置,通过 RDMA 网络传输 KV Cache。它的 EP(Expert Parallelism)设计还把 MoE 专家切到不同机器,整体复杂度很高,但单位算力下的吞吐量在公开数据里是顶尖水平。

Mooncake(Moonshot AI)也是 PD 分离的代表系统,强调把 KV Cache 作为一等公民——专门设计了一个全局 KV Cache 池,跨实例共享。它的核心创新点之一就是"以 KV Cache 为中心的调度"。

vLLM 在 0.7 之后也开始支持 PD 分离(叫 "disaggregated serving"),SGLang 同样有相关 PR。这条路线在 2024 年下半年到 2025 年成了开源推理框架的主要演进方向。

不分离的工程团队怎么办

PD 分离落地门槛高,多数中小团队不会自己部署。常见的折中是:

  • 用 Chunked Prefill 把大头收益拿到——单引擎里 Chunked Prefill 已经能拿走 60-70% 的延迟和吞吐改善。
  • 同质硬件按业务类型分实例——不同业务(短 QA / 长生成 / 摘要)部署在不同实例上,每个实例内部不分 PD 但请求路由分流。这是"业务级分离"而不是"阶段级分离"。
  • 直接用支持 PD 的商业服务——Anthropic、OpenAI、DeepSeek API 后端都做了类似优化,调用方拿到结果就行。

面试时可以这样答

Prefill-Decode 分离是把 Prefill 和 Decode 两个阶段拆到不同 GPU 实例上跑,一组专门做 Prefill 一组专门做 Decode,请求走完 Prefill 后把 KV Cache 通过高速网络传给 Decode 实例继续生成。

动机是 Prefill 和 Decode 对硬件和 batch 策略需求完全不同——Prefill 是计算密集要算力,单 batch 就能打满 GPU;Decode 是访存密集要带宽和大显存,必须靠大 batch 喂饱。混在同一台机器上时两套 batching 策略互相妥协,谁都不最优。Chunked Prefill 缓解了这个矛盾但解不彻底,PD 分离是把它彻底拆开。

收益和"长 Prompt + 长 Decode"场景成正相关。长 Prompt 短 Decode 的场景分离后能用便宜 GPU 做 Decode 省成本;长 Decode 场景分离后 Decode 端能做超大 batch 提吞吐;两端都长的 Agent 场景收益最大。但 Prompt 和 Decode 都很短的场景,KV Cache 传输的网络开销可能盖过收益。

核心难点是 KV Cache 跨机传输——70B 模型 8K 上下文 KV Cache 几个 GB,要在百毫秒级传完,得用 RDMA 网络。优化手段包括流式传输(chunk 算完就传和后续计算重叠)、KV 量化、拓扑感知调度。

真实落地系统包括 DeepSeek 推理、Moonshot 的 Mooncake,vLLM、SGLang 也都在 0.7 之后开始支持。中小团队落地门槛高,常见折中是先把 Chunked Prefill 用起来拿走大头收益,或者直接用支持 PD 的商业服务。

常见追问

  1. KV Cache 流式传输怎么和 Prefill chunk 计算 pipeline?两者完全并行还是有依赖?
  2. PD 分离后 Prefill 和 Decode 实例数量怎么配比?根据什么动态调整?
  3. 跨机 KV Cache 传输出错时怎么恢复?重新 Prefill 还是有兜底?