深度解读 📅 2026-07-24 ✍️ MagicNetWorld 编辑部

大模型推理部署解剖:PD 分离、AF 分离,和 micro-batch 流水线到底在优化什么

从算术强度与 KV 缓存账出发,把 Prefill/Decode 的负载差异写成公式,再逐层推导 PD 分离、AF 分离、micro-batch 流水线与 DualPipe 各自优化什么、代价是什么、什么规模才值得上。论文与官方文档口径逐条标注,本文自行推导的算式单独列出,站内厂商口径与推算值另行标明。

推理部署PD分离DualPipe系统工程

同一份开源权重,你自己在本地跑,每秒几十个 token;商业 API 却能稳定地服务成千上万人,单位成本还低一个数量级。差距几乎全在部署架构上,而不在模型本身。

要理解现代推理架构,得先接受一个不太直觉的前提:推理不是一种负载,而是两种负载,而且它们的瓶颈方向相反。本文按「直觉 → 符号约定 → 形式化推导 → 工程取舍 → 边界与未解」的顺序走一遍,所有具体数字都标注它来自哪份一手材料;凡是官方未公布的地方,我会直接写「官方未公布」,不替厂商补数。

一、先把直觉说清楚

先用一句话讲完本文的所有内容:Prefill 是”拿一堆 token 去撞同一批权重”,产能受算力限制;Decode 是”拿一个 token 去撞同一批权重”,产能受显存带宽限制。 两者的算术强度差了整整一个 batch 大小的倍数,所以它们在同一批 GPU 上必然互相拖累。PD 分离、AF 分离、micro-batch 流水线,本质上都是在回答同一个问题:既然两种负载的算术强度差一个数量级,凭什么让它们共用同一套硬件和同一张时间表?

三个层次的动作可以这样类比:

  • PD 分离=把工厂拆成两个车间,一个专做冲压(计算密集),一个专做装配(带宽密集),用传送带(RDMA)把半成品从冲压车间送到装配车间。代价是传送带本身会坏、会堵。
  • AF 分离=拆得更细:同一道工序里,「看图纸」(Attention,要反复翻 KV Cache)和「压机器」(FFN,要连续吃大矩阵)分开做,各自配最合适的机器。
  • micro-batch 流水线=不拆空间拆时间:把一大批活切成小份,让机器闲着的那几微秒被别人的活填上。DualPipe 则是把这条流水线从两端同时灌料,让同一个时刻 GPU 上既有前向又有反向。

这三个动作不互相替代,而是层层叠加。后面每一节都会给出对应的可计算量。

二、符号与术语约定(先定记号,再谈机制)

后面所有推导都用同一套记号,先把它们固定下来:

符号含义说明
BB一次前向里参与计算的 token 数Prefill 时 B≫1B \gg 1,Decode 时 B=1B = 1(单序列)或等于并发路数
SS上下文长度(token 数)决定 KV Cache 体量
NN模型总参数量DeepSeek-V3 为 671B
NaN_a每 token 激活参数量DeepSeek-V3 为 37B
WW权重占用的字节数W=N⋅pW = N \cdot p(按精度粗算)
pp权重/缓存精度字节数bf16 取 2,fp8 取 1
LLTransformer 层数DeepSeek-V3 为 61
nh, dhn_h,\ d_h注意力头数、每头维度DeepSeek-V3 均为 128
dc, dhRd_c,\ d_h^{R}MLA 的 KV 压缩维度、解耦 RoPE 维度DeepSeek-V3 为 512 与 64
PP流水线阶段数(PP)需为偶数才好做双向
mmmicro-batch 份数切分粒度
Tf, TcT_f,\ T_c单个 micro-batch 的计算时间、通信时间AF 分离的核心约束
AA算术强度,FLOPs / Byte本文的核心度量
A∗A^{*}机器的平衡点,Rpeak/BWR_{\text{peak}} / BW低于它=带宽瓶颈
RpeakR_{\text{peak}}加速器峰值算力H100 SXM bf16 稠密约 989 TFLOPS
BWBW显存带宽H100 SXM 为 3.35 TB/s

术语约定:本文的「一手来源」指论文原文、厂商官方文档或厂商官方博客;「本文推导」指用一手来源的硬件/架构参数做的计算,我会把它与来源数据分开标注,读者可以自行复算。

三、推理不是一种负载:Prefill 与 Decode 的算术强度推导

3.1 第一步:写出每 token 的 FLOPs 与字节数

对一个参数量为 NaN_a 的权重矩阵,处理 BB 个 token:

FLOPs=2 NaB\text{FLOPs} = 2 \, N_a B Bytes=Na p\text{Bytes} = N_a \, p

(权重只需从 HBM 读一遍就能服务整个 batch,这是「同一批权重被反复撞」的含义。)

于是权重部分的算术强度是

Aweight=2NaBNap=2BpA_{\text{weight}} = \frac{2 N_a B}{N_a p} = \frac{2B}{p}

3.2 第二步:代入精度,看两个阶段差多少

bf16 下 p=2p = 2,所以 Aweight=BA_{\text{weight}} = B。这是一个干净到近乎荒谬的结论:算术强度在数值上就等于 batch 里的 token 数。

  • Decode,B=1B = 1:A=1 FLOPs/ByteA = 1\ \text{FLOPs/Byte}
  • Prefill,B=4096B = 4096:A=4096 FLOPs/ByteA = 4096\ \text{FLOPs/Byte}

同一个 GPU、同一份权重,两种负载的算术强度差 4096 倍。这就是「为什么混部必然互相拖累」的定量版本——不是调度写得不好,是两者对硬件的诉求本就南辕北辙。

3.3 第三步:算出机器的平衡点

算术强度要跟机器的「算力/带宽比」比才有意义。对 H100 SXM:NVIDIA 官方规格给出 bf16 Tensor Core 1,979 TFLOPS、显存带宽 3.35 TB/s,并注明该数字为含稀疏性、不含稀疏时减半(即稠密约 989 TFLOPS)。

A∗=RpeakBW=989×10123.35×1012≈295 FLOPs/ByteA^{*} = \frac{R_{\text{peak}}}{BW} = \frac{989 \times 10^{12}}{3.35 \times 10^{12}} \approx 295 \ \text{FLOPs/Byte}

(用 fp8 稠密 1,979 TFLOPS 算,A∗≈591A^{*} \approx 591。)

对照 §3.2:Decode 的 A=1A = 1 比平衡点低 295 倍,也就是算力最多只能被用到约 0.3%;Prefill 在 4096 token 的 batch 下已经远在平衡点之上,反过来是显存带宽大量闲置。

反过来问一句更有用的问题:Decode 要并发多少路才能把算力吃满?

Aweight=B≥A∗≈295A_{\text{weight}} = B \ge A^{*} \approx 295

即 bf16 权重下大约要 300 路并发(单卡)。这个推导方法不是我自创的:MegaScale-Infer 论文对 A100 做过同样的计算——312 TFLOPS 除以 2 TB/s 得 156,论文直接写出 A100 上 batch size 至少要 156 个 token 才能充分利用矩阵乘能力。两个数字用的是同一个式子,只是硬件参数不同。这也顺带解释了为什么「小模型 + 低并发」的自部署永远跑不满卡:不是框架不行,是并发路数没到位。

3.4 第四步:Attention 部分的算术强度与 S 无关

权重之外还有 Attention。对一个 token 与 SS 个历史 token 做注意力,QK 转置与 PV 各需 2nhdhS2 n_h d_h S 次浮点运算,共 4nhdhS4 n_h d_h S;而它要读的 K、V 是 2Snhdh2 S n_h d_h 个元素。于是

AattnMHA=4nhdhS2Snhdh p=2pA_{\text{attn}}^{\text{MHA}} = \frac{4 n_h d_h S}{2 S n_h d_h \, p} = \frac{2}{p}

上下文长度 SS 被约掉了。 bf16 下 MHA 的 Attention 算术强度恒为 1——跟 Decode 完全一样,无论上下文多长,它永远是彻头彻尾的带宽瓶颈。这解释了为什么 Decode 阶段「越长的上下文越慢」,而且慢得线性。

换成 MLA 会怎样?FLOPs 不变(仍然要在 nhn_h 个头上算完整注意力),但缓存只读 dc+dhRd_c + d_h^{R} 而非 2nhdh2 n_h d_h:

AattnMLA=4nhdhS(dc+dhR)S pA_{\text{attn}}^{\text{MLA}} = \frac{4 n_h d_h S}{(d_c + d_h^{R}) S \, p}

代入 DeepSeek-V3 的架构参数(nh=dh=128n_h = d_h = 128、dc=512d_c = 512、dhR=64d_h^{R} = 64,这些值出自技术报告的模型超参数一节):

AattnMLA=4×128×128(512+64)×2=5129≈56.9 FLOPs/ByteA_{\text{attn}}^{\text{MLA}} = \frac{4 \times 128 \times 128}{(512 + 64) \times 2} = \frac{512}{9} \approx 56.9 \ \text{FLOPs/Byte}

同一个 Attention,MLA 把算术强度抬高了约 57 倍(2nh/4.5=56.92n_h / 4.5 = 56.9)。它仍然低于平衡点 295,所以 Decode 依旧带宽受限——但从「差 295 倍」变成了「差 5 倍」,这是量级上的改变,也是 §四 显存账的同一个 57 倍。

四、KV 缓存:把两种负载的差距写成显存账

4.1 每 token 的缓存公式

DeepSeek-V2 技术报告的 Table 1 直接给了各种注意力机制的每 token KV 缓存元素数(以元素个数计,不考虑存储精度):

MHA:2nhdhLGQA:2ngdhLMQA:2dhLMLA:(dc+dhR)L\text{MHA}: 2 n_h d_h L \qquad \text{GQA}: 2 n_g d_h L \qquad \text{MQA}: 2 d_h L \qquad \text{MLA}: (d_c + d_h^{R}) L

报告并给出 DeepSeek-V2 的取值:dc=4dhd_c = 4 d_h、dhR=dh/2d_h^{R} = d_h / 2,因此 MLA 的缓存相当于「只有 2.25 个分组的 GQA」。V2 报告的结论口径是相比 DeepSeek 67B 把 KV 缓存降低 93.3%——注意这个 93.3% 的基线是自家上一代稠密模型,而不是同架构的 MHA。

4.2 同一架构下:MLA vs MHA 到底差多少

把两个式子相除,消掉 dhd_h 与 LL:

KVMHAKVMLA=2nhdhL(dc+dhR)L=2nh4.5\frac{\text{KV}_{\text{MHA}}}{\text{KV}_{\text{MLA}}} = \frac{2 n_h d_h L}{(d_c + d_h^{R}) L} = \frac{2 n_h}{4.5}

代入 nh=128n_h = 128(V3 报告口径):

2×1284.5≈56.9\frac{2 \times 128}{4.5} \approx 56.9

所以在同一架构、同一头数下,MLA 的 KV 缓存大约是 MHA 的 1/57。 这解释了第一节里「要传的 KV 小 57 倍」的确切来历:它不是厂商宣传口径,而是表 1 公式在 nh=128n_h = 128 处的直接结果。(同一笔缓存账在 本栏目 MLA 一文 里按 MHA/MQA/GQA/MLA 横向展开,这里只取推导结果。)

4.3 代入 DeepSeek-V3 的具体字节数

用 §4.1 的 MLA 式子,dc+dhR=512+64=576d_c + d_h^{R} = 512 + 64 = 576,L=61L = 61,bf16(p=2p = 2):

KV per token=576×61×2=70,272 B≈68.6 KiB\text{KV per token} = 576 \times 61 \times 2 = 70{,}272 \ \text{B} \approx 68.6\ \text{KiB}

也就是业界常说的「DeepSeek-V3 每 token 约 70 KB」的口径来源。

作为反事实,如果 V3 用 MHA:

2×128×128×61×2=3,997,696 B≈3.81 MiB2 \times 128 \times 128 \times 61 \times 2 = 3{,}997{,}696 \ \text{B} \approx 3.81\ \text{MiB}

两者相差正是 56.9 倍。

4.4 并发上限:从显存账倒推能服务多少人

单卡能同时挂多少条序列,取决于还剩多少显存:

Cmax⁡=Mtotal−Mweights−MactS×KV per tokenC_{\max} = \frac{M_{\text{total}} - M_{\text{weights}} - M_{\text{act}}}{S \times \text{KV per token}}

用 DeepSeek 官方推理系统口径做一次估算(以下参数化假设明确标注,读者可改参复算):

  • 权重按 fp8 计,671 GB;decode 部署单元是 EP144(18 节点,144 路专家并行),每卡分摊约 671/144≈4.7 GB671 / 144 \approx 4.7\ \text{GB}
  • 单卡 H800 80 GB,留给 KV 与激活约 75 GB
  • 上下文取 DeepSeek 官方公布的平均 KV 长度 4,989 token

单请求 KV:4989×70,272≈350.6 MB4989 \times 70{,}272 \approx 350.6\ \text{MB}

Cmax⁡≈75 GB0.3506 GB≈214 路/卡C_{\max} \approx \frac{75\ \text{GB}}{0.3506\ \text{GB}} \approx 214 \ \text{路/卡}

同样的算式换成 MHA:单请求 KV 为 3,997,696 B×4989≈19.94 GB3{,}997{,}696\ \text{B} \times 4989 \approx 19.94\ \text{GB}(十进制口径,1 GB = 10910^9 B):

Cmax⁡MHA≈7519.94≈3.76 路/卡C_{\max}^{\text{MHA}} \approx \frac{75}{19.94} \approx 3.76 \ \text{路/卡}

(若整条账改用二进制口径,75 GB 折 76,800 MiB、单请求 18.58 GiB,结果是 4.04 路——两种口径各自自洽,混用就会算错;本节统一用十进制。)

同一个 57 倍,落到并发上就是 214 路和 3.76 路的区别(214/3.76≈56.9214 / 3.76 \approx 56.9,与 §4.2 的比值自洽)。 这个差距正是「自部署 MoE 大模型为什么必须先看显存账」的算术解释,也是 MLA 与 PD 分离必须一起看的原因:KV 越小,能摊到 Decode 池的并发越多,而 Decode 池的产能恰恰就是靠并发堆出来的(§3.3)。

一张图说明 KV Cache 是怎么被拆着算出来的:

flowchart LR
    A["输入 token"] --> B["写 KV 到缓存"]
    B --> C{"注意力机制"}
    C -- "MHA" --> D["每 token 2 n_h d_h L 个元素"]
    C -- "MLA" --> E["每 token (d_c + d_h_R) L 个元素"]
    D --> F["读全部 K,V 做注意力"]
    E --> F
    F --> G["下一个 token"]
    G -.-> B

这张图说明了什么:Decode 每一轮都在执行「写一个 token 的 KV → 读回全部历史 KV」这个循环,而读回的那部分体量完全由注意力机制的每 token 缓存公式决定;把 MHA 换成 MLA,循环里被读的数据量降到约 1/57,循环周期因此大幅缩短。图中的回边(虚线)就是自回归的本质:缓存只增不减。

五、PD 分离:拆开之后各自的自由,和必须付的代价

PD 分离(Prefill-Decode Disaggregation)的动作非常直白:Prefill 池和 Decode 池分开部署,各自按负载特征配比资源;Prefill 算完 KV 之后,通过高速网络把 KV 传给 Decode 节点接力生成。

5.1 一次请求到底怎么走

sequenceDiagram
    autonumber
    participant C as 客户端
    participant R as 路由与调度
    participant P as Prefill 实例池
    participant X as KV 传输通道
    participant D as Decode 实例池
    C->>R: 提交请求, prompt 长度 S
    R->>P: 选一个 prefill 实例并握手
    P->>P: 并行前向, 产出首 token 与全部 KV
    P->>X: 逐层异步推送 KV 块
    X->>D: RDMA 写入预分配的 KV 槽位
    D->>D: 加入 continuous batching 逐 token 解码
    D-->>R: 流式回传 token
    R-->>C: SSE 流式输出
    D->>P: 全部 KV 落地后通知 prefill 释放块

这张图说明了什么:PD 分离把「一次请求」从一条流水线拆成两段独立排程,中间多出一个必须串行完成的交接点(KV 传输,图中第 5–6 步)。Prefill 池的产能由算力决定,Decode 池的产能由并发与带宽决定,两者因此可以各自单独扩容——而代价集中在那一个交接点上:它既是延迟项(TTFT 多等一段),也是故障项和带宽消耗项。

SGLang 的实现细节可以印证这条链路:Prefill Server 与 Decode Server 先握手建立 sender/receiver,Decode Server 预分配 KV 缓存后通知 Prefill 开始前向;传输走 RDMA(队列对建连、散列表元素搬运非连续内存块),并且收发在后台线程完成,不阻塞调度器事件循环。vLLM 官方文档列出的分离动机有两条:把 TTFT 和 ITL 分开调,以及控制尾部 ITL——因为混部时 vLLM 会在解码途中插入 prefill 任务,直接把长尾延迟顶上去。

先对齐两个术语:TPOT(time per output token)与 ITL(inter-token latency)指的是同一个指标,前者是 DistServe 等论文的写法,后者是 vLLM 官方文档的写法,本文按来源各用其词。另外,被引的 vLLM 文档同页还留了一句加粗的反向声明:Disaggregated prefill DOES NOT improve throughput。也就是说,PD 分离优化的是延迟与 goodput(满足延迟约束的有效吞吐),而不是裸吞吐——这也是本文后面所有收益数字都用 goodput 或延迟口径的原因,不能把它们当成”吞吐提升 X 倍”来读。

5.2 KV 传输要多久:一个跟上下文长度无关的常数比

KV 传输的绝对时间随 SS 线性增长:

tcomm(S)=S×KV per tokenBWnett_{\text{comm}}(S) = \frac{S \times \text{KV per token}}{BW_{\text{net}}}

取 S=32,768S = 32{,}768(32K 上下文):

tcomm=32768×70,27250×109≈46.0 mst_{\text{comm}} = \frac{32768 \times 70{,}272}{50 \times 10^{9}} \approx 46.0\ \text{ms}

(50 GB/s 是 DeepSeek-V3 报告披露的集群 IB 带宽口径;同一份报告给出 NVLink 为 160 GB/s,约为 IB 的 3.2 倍,对应 14.4 ms。)

关键问题是:这个开销相对 Prefill 自身耗时是什么量级?把两式相除,SS 会被约掉:

tcommtcomp=S⋅KV per token/BWnet2NaS/Rpeak=KV per token⋅Rpeak2Na⋅BWnet\frac{t_{\text{comm}}}{t_{\text{comp}}} = \frac{S \cdot \text{KV per token} / BW_{\text{net}}}{2 N_a S / R_{\text{peak}}} = \frac{\text{KV per token} \cdot R_{\text{peak}}}{2 N_a \cdot BW_{\text{net}}}

代入本篇前面核验过的参数(KV per token =70,272= 70{,}272 B、Rpeak=989R_{\text{peak}} = 989 TFLOPS、Na=37N_a = 37B、BWnet=50BW_{\text{net}} = 50 GB/s):

tcommtcomp=70272×9.89×10142×37×109×50×109≈1.9%\frac{t_{\text{comm}}}{t_{\text{comp}}} = \frac{70272 \times 9.89 \times 10^{14}}{2 \times 37 \times 10^{9} \times 50 \times 10^{9}} \approx 1.9\%

这是一个与上下文长度无关的常数比,约 2%。 这正是 PD 分离在工程上能够成立的根本原因:KV 传输量与 Prefill 计算量都随 SS 线性增长,比值恒定在百分之几的量级,而它换来的是两个池各自可以按最优并行策略部署。反过来,这个结论也给出了 PD 分离的适用边界——它成立的前提是网络带宽与算力处于同一量级(本文用的是 50 GB/s 对 989 TFLOPS)。如果网络只有 1–2 GB/s,这个比值会跳到 50% 以上,分离就变成负收益。

5.3 拆开之后拿到什么:公开数字

  • DistServe(arXiv 2401.09670,2024-01;OSDI 2024)是这条路线早期的奠基工作之一——它并不是最早的:Splitwise(arXiv 2311.18677)在 2023 年 11 月就已提出把 prompt 计算与 token 生成拆到不同机器。DistServe 的核心主张是把 prefill 与 decoding 分到不同 GPU 上消除互相干扰,并把资源分配与并行策略按阶段协同优化,以 goodput(满足延迟约束的有效吞吐)为目标。
  • Splitwise(微软研究院等)把 prompt 计算与 token 生成放到不同机器上,并指出 token 生成阶段并不需要最新一代 GPU 的算力,可以用功耗与成本更低的硬件跑;论文报告相同成本与功耗预算下可交付 2.35 倍吞吐,或 1.4 倍吞吐同时降低 20% 成本。
  • SGLang 的实测最能说明规模效应:12 节点 × 8 张 H100(共 96 卡),PD 分离 + 大规模 EP,2000 token 输入下达到每节点 52.3k 输入 token/s 与 22.3k 输出 token/s;自部署折算约 0.20 美元/百万输出 token,约为官方 DeepSeek Chat API 的 1/5,输出吞吐相比同资源的朴素张量并行提升最多 5 倍。分阶段看:Prefill 侧 4 节点(EP32)在 1K/2K/4K prompt 下分别为 57,674 / 54,543 / 50,302 token/s/节点,相比 TP16 基线约 3.3 倍;Decode 侧 9 节点(EP72)在 2K 输入下 22,282 token/s/节点,相比 TP16 约 5.2 倍。SGLang 还主动声明:DeepSeek 官方 profile 的吞吐约为其生产环境的两倍,所以跨来源的数字不能直接横向比。
  • vLLM + AMD MORI-IO 给出了一个反直觉的结论:PD 分离不必是多机集群的事。在单台 8 卡 MI300X 节点上(0–3 卡做 prefill、4–7 卡做 decode,KV 走 RDMA 传输),同一批 8 卡上对比混部,goodput 提升 2.5 倍,且 token 生成延迟更稳定。AMD 同时点明了代价:KV「可能达到数 GB 级」,传输本身如果不处理好,就会变成抵消分离收益的新瓶颈。

5.4 代价清单

  • KV 传输:绝对量随上下文线性增长;必须落在 TTFT 关键路径上(Decode 得等 KV 到齐才能开始)。
  • 调度复杂度:需要 prefill/decode 配对、预分配 KV 槽位、完成通知与资源回收(SGLang 的握手协议、Mooncake 的 Conductor 全局调度器都是为此而生)。
  • 两池配比无法自适应:这是 NVIDIA 强调「动态 rate matching」的原因——配比失衡时,Decode 卡会空等 KV,或 Prefill 任务在队列里排队。NVIDIA 明确把 rate matching 的输入列为 prefill 队列长度、decode 侧 KV 块利用率,以及 TTFT / ITL 这类 SLA。
  • 框架成熟度不一:vLLM 官方文档把 disaggregated prefilling 标为 experimental;SGLang 已作为主要路径支持;NVIDIA Dynamo 则把它做成了产品化能力(分离 prefill/decode、KV-aware 路由、NIXL 传输)。评估框架时这是必问项。

5.5 KV 缓存分层:PD 分离之上再加一层

Mooncake(Kimi 的生产服务系统,FAST ‘25 论文)在 PD 分离之上把整个 GPU 集群闲置的 CPU、DRAM、SSD 与 RDMA 资源汇成一个分布式 KV 缓存池。论文给出的生产数字:Kimi 在 A800 与 H800 集群上分别能多承接 115% 和 107% 的请求;实测缓存命中率最高比本地缓存高 2.36 倍,带来最多 48% 的 prefill 计算时间节省;系统当前跨数千节点运行、每天处理超过 1000 亿 token。

容量账也很值得记:论文的理论分析显示,3M token 的本地缓存容量在多数负载下拿不到理论最高命中率的一半,而要接近理论最高命中率需要 50M token 级别的容量,等价于至少汇聚 20 个节点的 DRAM。这从另一个角度说明:PD 分离的收益天花板,很大程度由缓存池的容量和命中率决定,而不是由分离动作本身决定。

顺带对齐一个站内口径:本站 Kimi K3 条目 记录的厂商说法是「编程场景借助 Mooncake 分离式推理架构缓存率超 90%」。这是厂商口径,Mooncake 论文本身没有公布这个数字——论文给的是「命中率最高比本地缓存高 2.36 倍」与「3M token 的本地缓存容量在多数负载下拿不到理论最高命中率的一半」。两个口径不冲突,但不能互相替代:前者是厂商对自家生产环境的说法,后者是有明确实验设定的论文数字。

六、AF 分离:把拆分粒度推到算子里

6.1 为什么按阶段拆还不够

对稠密模型,Attention 与 FFN 都会被 batch 喂饱。但对 MoE 模型,稀疏激活把 FFN 从计算密集变成了访存密集(all-to-all 通信与专家负载不均的来源见 本栏目 MoE 一文):MegaScale-Infer 论文给出了完整的机制链条——

  • 先看 FFN 要多少 batch 才能算得动。A100 上需要 batch ≥ 156 个 token(论文写作 b≥F/B=312 TFLOPS/2 TB/sb \ge F/B = 312\ \text{TFLOPS} / 2\ \text{TB/s},与本文 §3.3 的推导同一个式子);
  • 但 MoE 的 top-k 路由会把 token 打散:batch 为 156 时,每个专家平均只收到 156×2/8=39156 \times 2 / 8 = 39 个 token(以 8 专家、top-2 为例);
  • 39 远小于 156,于是理论 MFU 上限只有 top-k 除以专家数——8 专家 top-2 就是 25%。稀疏度越高,浪费越大。

AF 分离(Attention-FFN Disaggregation,论文里称为 disaggregated expert parallelism)的解法是把每层里的 Attention 与 FFN 模块拆到不同的设备池:Attention 模块用数据并行复制(同时持有 KV Cache),FFN/专家模块用专家并行切分。关键收益有两条:独立扩缩(两者可以各自选并行策略)与异构部署(Attention 用大显存带宽的卡,FFN 用算力强、更便宜的卡)。而把多个 Attention 副本上的请求汇聚到同一组专家上,每个专家的有效 batch 被重新放大,FFN 又变回计算密集。

flowchart LR
    subgraph AP["Attention 节点池: 数据并行复制, 持有 KV Cache"]
        A1["Attention 副本 1"]
        A2["Attention 副本 2"]
    end
    subgraph EP["Expert 节点池: 专家并行切分, 每卡存若干专家"]
        E1["专家组 A"]
        E2["专家组 B"]
    end
    A1 -- "dispatch: token 发往专家" --> E1
    A1 -- "dispatch" --> E2
    A2 -- "dispatch" --> E1
    A2 -- "dispatch" --> E2
    E1 -- "combine: 分部结果回传" --> A1
    E1 -- "combine" --> A2
    E2 -- "combine" --> A1
    E2 -- "combine" --> A2

这张图说明了什么:AF 分离把原来发生在一个 MoE 层内部的 all-to-all 通信,改写成了「M 个 Attention 卡 ↔ N 个 Expert 卡」的跨池通信(论文称之为 M2N)。注意回程是完整的 M2N 网格,而不是一条对角线:每个 Attention 副本把 token 派发给了哪几个专家组,就必须从这几个专家组收齐各自算出的分部结果再汇总(fan-in)——图上四条 combine 箭头就是这个扇入。两条好处(独立扩缩、异构部署)都来自汇合点这个结构本身;而它带来的新问题也在这张图上——任意一侧算完,另一侧若没活干就闲置,所以必须有 micro-batch 交错来填。

6.2 micro-batch 数的下界:可以推出来

设单个 micro-batch 的计算时间为 TfT_f、通信时间为 TcT_c,论文给出三条约束(通信短于计算;整层的全局 batch 前向时间足以覆盖单个 micro-batch 穿过该层的时间等),推出最少 micro-batch 数:

m≥2×(1+TcTf),0<TcTf<1m \ge 2 \times \left(1 + \frac{T_c}{T_f}\right), \qquad 0 < \frac{T_c}{T_f} < 1

这个式子的含义直白得漂亮:因为 Attention 与 FFN 之间要「乒乓」两个方向,所以至少要 2 份;而通信占比越高,需要越多份来互相遮盖——当 Tc/Tf→1T_c / T_f \to 1(通信与计算同量级)时下界趋近 4。

Tc=0.5Tf⇒m≥3;Tc→Tf⇒m≥4T_c = 0.5 T_f \Rightarrow m \ge 3; \qquad T_c \to T_f \Rightarrow m \ge 4

同一篇论文报告的结果是:相比同类最优方案,每 GPU 解码吞吐提升最多 1.90 倍;在异构集群上每美元吞吐提升 1.7 倍;其自研 M2N 通信库相比 NCCL 吞吐高 4.2 倍、延迟低 68.2%。需要注意的是:AF 分离仍不是主流框架的默认路径(这篇是字节 Seed 与北大的系统论文),但已不再是「只有自研」的局面:vLLM 官方在 2026-07-23 发布了实验性的 AFD Plugin(仓库 vllm-project/afd-plugin,通过 vllm.general_plugins 入口接入、无需改 vLLM 源码,覆盖 NVIDIA GPU 与昇腾 NPU,含 DeepSeek V2/V3 系与 GLM MoE 的模型包装器)。官方博客同时给出了受控实测,也顺便划出了边界:DeepSeek-V3.2 W8A8 在昇腾 910C 上,64A16F(64 个 Attention rank + 16 个 FFN rank)相对 EP64 基线在 16K 输入下 +11.3%、32K 输入下 +9.0%,而 48A16F 反而是 -5.3% / -10.0%——AF 分离本身不保证收益,Attention 与 FFN 的配比才是关键。所以准确的说法是:AF 分离有了官方实验性路径(非默认),但离「业界默认做法」还很远。这一点下节的对照表会再列一次。

七、micro-batch 与流水线气泡:把公式写出来

如果说 PD/AF 分离是「空间上拆」,流水线就是「时间上叠」。这一节把气泡比例算到底。

7.1 朴素流水线的气泡比例

模型大到单卡装不下时按层切到多张卡(流水线并行,PP 阶段数为 PP)。最朴素的整批流动(一批数据依次经过卡 1 → 卡 2 → …)会让任一时刻只有一张卡在干活;把批次切成 mm 个 micro-batch 错峰流动可以填坑,但填不满——因为流水线的启动(warm-up)与收尾(cool-down)阶段天然没有足够多的 micro-batch 供填充。

1F1B 调度的气泡时间为 (P−1)(F+B)(P-1)(F+B)(FF 为前向 chunk 时间,BB 为反向 chunk 时间),有效计算时间为 m(F+B)m(F+B),于是气泡比例:

ρ(m)=(P−1)(F+B)m(F+B)+(P−1)(F+B)=P−1m+P−1\rho(m) = \frac{(P-1)(F+B)}{m(F+B) + (P-1)(F+B)} = \frac{P-1}{m + P-1}

取 P=16P = 16:

micro-batch 数 mmm=16m=16m=32m=32m=64m=64m=128m=128m=256m=256
1F1B 气泡比例 ρ\rho48.4%31.9%19.0%10.5%5.5%

两个可以直接用的结论:(1)micro-batch 数与阶段数相同时,接近一半的时间是气泡;(2)气泡按 (P−1)/(m+P−1)(P-1)/(m+P-1) 衰减,把 (P−1)/(m+P−1)<10%(P-1)/(m+P-1) < 10\% 展开得 m>9(P−1)m > 9(P-1),P=16P = 16 时即 m≳136≈8.5Pm \gtrsim 136 \approx 8.5P。 这解释了为什么大规模流水线训练的 micro-batch 数总要开到几十上百。

7.2 DualPipe 把这个式子改写成了什么

DeepSeek 官方 DualPipe 仓库给出了同一组对比(PP\mathit{PP} 为阶段数,F&B\mathit{F\&B} 表示互相重叠的一对前向与反向 chunk 的执行时间,W\mathit{W} 表示「backward for weights」chunk 的时间):

方法气泡每设备参数副本每设备激活占用设备数
1F1B(PP−1)(F+B)(\mathit{PP}-1)(\mathit{F}+\mathit{B})1×PP\mathit{PP}PP\mathit{PP}
ZB1P(PP−1)(F+B−2W)(\mathit{PP}-1)(\mathit{F}+\mathit{B}-2\mathit{W})1×PP\mathit{PP}PP\mathit{PP}
DualPipe(PP/2−1)(F&B+B−3W)(\mathit{PP}/2-1)(\mathit{F\&B}+\mathit{B}-3\mathit{W})2×PP+1\mathit{PP}+1PP\mathit{PP}
DualPipeV(PP/2−1)(F&B+B−3W)(\mathit{PP}/2-1)(\mathit{F\&B}+\mathit{B}-3\mathit{W})2×PP+1\mathit{PP}+1PP/2\mathit{PP}/2

三处改动值得逐条读:

  1. 前导因子从 (PP−1)(\mathit{PP}-1) 变成 (PP/2−1)(\mathit{PP}/2-1):气泡量级直接减半,因为现在是两条流水线互相填坑。
  2. F+B\mathit{F}+\mathit{B} 变成 F&B\mathit{F\&B}:一对前向与反向 chunk 被安排成时间上重叠,所以这一项本身就小于两者之和。
  3. 代价写在表里:每设备要放 2 份参数副本(模型参数翻倍),每设备激活占用从 PP\mathit{PP} 涨到 PP+1\mathit{PP}+1。DeepSeek-V3 报告对这种代价给出的解释是:训练时用了很大的 EP size,参数副本翻倍的显存影响不显著。

同一节里报告还给出 DeepSeek-V3 的实际配置:16 路流水线并行、64 路专家并行、跨 8 个节点,外加 ZeRO-1 数据并行。

7.3 流水线气泡为什么必须算清楚

因为气泡直接等价于钱。同一份技术报告披露:DeepSeek-V3 完整训练用了 2.788M H800 GPU 小时。气泡比例是个乘法因子——把 ρ\rho 从 48% 压到 5%,等于白拿将近一倍的有效算力。这也是 DualPipe 值得单独开源的原因。

八、DualPipe 的双向流水线:把 all-to-all 藏进计算

8.1 它要解决的问题有一个确切的量级

DeepSeek-V3 报告写得很直白:跨节点专家并行带来的通信开销,使得计算与通信的比例大约是 1:1。这句话是整个 DualPipe 设计的前提。它意味着按部就班地「先算完再通信」是不可能快的——你只能选择把通信藏起来。

8.2 DualPipe 的三个动作

  1. 把每个 chunk 切成四块:attention、all-to-all dispatch、MLP、all-to-all combine。对反向 chunk,attention 与 MLP 还要再各自拆成「backward for input」和「backward for weights」两部分(沿用 ZeroBubble 的做法),此外还有一个 PP 通信组件。
  2. 在一对前向/反向 chunk 内部重排这些组件,并手工调整通信与计算各自占用的 SM 比例。报告的说法是:在这套重叠策略下,all-to-all 与 PP 通信都能被完全藏住。
  3. 双向调度:从流水线两端同时灌入 micro-batch,使同一个设备上「一队的前向」与「另一队的反向」在时间上交错。官方仓库给出的示例是 8 个 PP rank + 20 个 micro-batch 双向运行。
flowchart TB
    subgraph CH["一个 chunk 被切成四块"]
        direction LR
        X1["attention"] --> X2["all-to-all dispatch"] --> X3["MLP"] --> X4["all-to-all combine"]
    end
    subgraph PP["双向流水线调度"]
        direction LR
        P0["PP rank 0"] --> P1["PP rank 1"] --> P2["…"] --> P3["PP rank N"]
    end
    FWD["正向队列: 从 rank 0 端注入 micro-batch"] --> PP
    BWD["反向队列: 从 rank N 端注入 micro-batch"] --> PP
    CH -. "通信块插进计算块的间隙" .-> PP

这张图说明了什么:DualPipe 同时对两个维度动手——纵向把 chunk 切细到「计算块 / 通信块」的粒度,横向把流水线灌成双向。切细是为了让通信块有缝隙可插,双向是为了让被插进去的通信有别的计算可以盖住它。两者缺一不可:只切细而没有双向,气泡依旧填不满;只双向而不切细,通信就没有可对齐的时间粒度。

8.3 一个必要区分:DualPipe 是训练侧方案

原文里所有关于 DualPipe 的论述都在「3.2 Training Framework」一节下,配置是 16 路 PP、64 路 EP、ZeRO-1 DP——这是训练配置。DualPipe 本身不是推理方案。 但「micro-batch 切分 + 计算/通信重叠」的思想在推理侧同样无处不在,下一节给出推理侧的对等物,以及它们各自的公开收益数字。

九、推理侧的同源技术

9.1 chunked prefill 与 stall-free 调度

Sarathi-Serve 的出发点是同一个观察:混部时新来的 prefill 会打断正在进行的 decode。它给出的数字很有说服力:

  • 朴素的混合批(整段 prefill 与 decode 同批,即 Orca 式做法)会让 TBT(相邻 token 间隔)延迟相比纯 decode 批次暴涨最多 28.3 倍;
  • 把 prefill 切成固定大小的 chunk 再与 decode 拼成混合批后,延迟波动被压紧;
  • 吞吐侧收益:单张 A100 上 Mistral-7B 提升最多 2.6 倍,8 张 A100 上 Falcon-180B 提升最多 6.9 倍(对比 Orca)。

它同时点出了两个容易被忽略的工程细节:

  • 分块不是免费的:一个被切成 NN 块的 prefill,其第 1 块的 KV 要被加载 N−1N-1 次,第 2 块要被加载 N−2N-2 次……不过论文实测即使在很小的 chunk 尺寸下,prefill 的 attention 仍然是计算受限的。
  • chunk 尺寸必须对齐硬件瓦片:GPU 矩阵乘按瓦片切分给线程块,维度不能整除瓦片时会出现「瓦片量化」浪费。论文实测的一个例子是 chunk 取 257 相比取 256,prefill 时间增加 32%。
  • 另外,线性层的执行时间在 batch 128–512 token 区间基本是平的(等权重从 HBM 取完的时间里,多算几个 token 是”免费”的),prefill 大约在 512 token 就基本打满算力——这直接给了「token budget 该设多大」的物理依据。

9.2 两批重叠(TBO):SGLang 侧的实测数字

SGLang 的 two-batch-overlap(TBO)与 DeepSeek 的 dual-batch overlap 是同一件事:把一批请求切成两个 micro-batch,一份的计算盖住另一份的通信。公开数字:

  • 在与朴素方案处理相同 token 数的前提下,吞吐提升 27% 到 35%;
  • 更重要的收益是显存:朴素配置在每设备 16,384 token 时 OOM,TBO 让 16,384 token/device 的批能跑起来,综合下来相比其他最优配置再提升 40.5%;
  • SGLang 还解释了为什么 decode 侧的 TBO 收益与 prefill 不同:decode 的通信核要么占满 SM(收发时)要么完全不占(等对端时),因此不会和计算核抢资源——这与 prefill 侧的情况相反。

9.3 DeepSeek 官方推理侧的对应做法

DeepSeek 官方推理系统文档给出了两套不同的重叠策略,注意它与训练侧的 DualPipe 不是同一个东西:

  • Prefill 阶段用双批重叠:把一批请求切成 2 个 micro-batch 交替执行,一份的通信成本被另一份的计算盖住。
  • Decode 阶段用 5 阶段流水线:因为各阶段耗时本来就不均衡,官方把 attention 层再拆成两步,构成 5 阶段流水线,实现”无缝”的计算-通信重叠。

这一节所有内容都指向同一个判断:micro-batch 与重叠是推理架构里最普适、也最不依赖具体厂商的一层优化。PD 分离与 AF 分离是「要不要买专用硬件」的选择题,而 micro-batch 与重叠是「买了之后能不能用好」的必答题。

十、对照表:各自优化什么、代价是什么

技术拆分的维度优化什么主要代价本文读到的一手证据
PD 分离按推理阶段(空间)两池各自按负载特征配比;TTFT 与 ITL 可分别调;消除 prefill 对 decode 的干扰与尾延迟KV 跨节点传输(落在 TTFT 关键路径)、配对与预分配调度复杂度、两池配比需要动态 rate matching、框架成熟度不一DistServe(OSDI 2024);vLLM 官方文档列出两条动机;Splitwise 报 2.35× 吞吐或 1.4× 吞吐 + 20% 降本;SGLang 12 节点 × 8 H100 实测;AMD MORI-IO 单节点 8 卡 goodput 2.5×
KV 缓存分层按存储层级(空间)把 GPU 集群闲置的 CPU/DRAM/SSD/RDMA 汇成全局 KV 池,抬高缓存命中率、减少冗余 prefill需要分布式缓存与全局调度器;命中率依赖容量与负载分布,理论最高命中率需要 50M token 级容量Mooncake(FAST ‘25):Kimi 多承接 115%/107% 请求;命中率最高比本地缓存高 2.36 倍、prefill 计算时间最多省 48%
AF 分离按算子类型(空间)Attention 与 FFN 各自用最优并行策略;异构部署(不同阶段用不同性价比的卡);把跨副本请求汇聚后 FFN 重新变回计算密集拆解后两侧互相等待产生闲置(需 micro-batch 乒乓)、层内 all-to-all 变成 M2N 通信、需要专门的性能模型做部署规划;Attention/FFN 配比不当会吃掉收益(vLLM 官方 AFD 插件受控实测中 48A16F 相对 EP64 为负收益)MegaScale-Infer:每 GPU 解码吞吐最多 1.90×,异构集群每美元吞吐 1.7×,自研 M2N 相比 NCCL 吞吐 4.2×、延迟低 68.2%;vLLM 官方 AFD Plugin(2026-07,experimental)实测 64A16F 相对 EP64 在 16K/32K 输入下 +11.3% / +9.0%
micro-batch + 气泡控制按时间把流水线启动/收尾的气泡从 (P−1)/(m+P−1)(P-1)/(m+P-1) 压下去;由 (P−1)/(m+P−1)<10%(P-1)/(m+P-1) < 10\% 解得 m>9(P−1)m > 9(P-1)(P=16P=16 时约 136≈8.5P136 \approx 8.5P)micro-batch 太小会降低算术强度、抬高固定开销;调度与显存(激活)占用上升1F1B 气泡公式与 DualPipe 官方对比表(本文逐项复算)
计算/通信重叠(TBO / dual-batch)按时间用一份 micro-batch 的计算盖住另一份的通信;在 DeepSeek-V3 上对应的前提是通信:计算 ≈ 1:1需要更大的有效 batch 与更多显存;调度需要保证发射顺序(否则 CPU 阻塞会把 GPU 拖空)DeepSeek 官方推理系统文档(prefill 双批 / decode 5 阶段);SGLang TBO 吞吐 +27%~35%、显存换到 16,384 token/device
DualPipe / DualPipeV时间 + 双向把 all-to-all 与 PP 通信完全藏进计算;气泡前导因子从 (PP−1)(\mathit{PP}-1) 降到 (PP/2−1)(\mathit{PP}/2-1)每设备 2 份参数副本、每设备激活从 PP\mathit{PP} 涨到 PP+1\mathit{PP}+1;深度依赖框架定制(需自实现重叠的前反向)DeepSeek-V3 报告 §3.2.1 与官方 DualPipe 仓库
chunked prefill按时间(调度粒度)长 prefill 不再阻塞 decode;把 TBT 抖动从最多 28.3× 压到可控分块带来 KV 重复加载;chunk 尺寸未对齐硬件瓦片时浪费(257 vs 256 实测差 32%)Sarathi-Serve(OSDI 2024)

十一、工程含义:什么规模才值得上这些架构

把所有数字收拢成三档,便于做决策:

第一档:单机 8 卡以内、中小模型、并发不高。 结论是不要上 PD 分离。SGLang 的立场很明确:统一模式(unified mode)在实验、小模型或低 QPS 场景完全够用;vLLM 也把 disaggregated prefilling 标为 experimental。此时更该做的是把 continuous batching、paged attention、prefix caching 这些基础项做扎实——Mooncake 论文的对比里就包含 vLLM 的 prefix caching 与 chunked prefill 两条基线。

这里顺带对齐另一个站内口径:本站 Kimi K3 条目 给出的自部署硬件是「完整 2.8T 参数需要 8×A100 80GB 或 8×H100」——注意站内把它明确标注为推算值(不是官方建议、也不是官方部署文档口径),量化到 4-bit 可能降到 4×A100 级别。所以「8 卡」是自部署超大 MoE 的入场线,远不是 PD 分离的适用线:入场线之后才轮到下面的分档判断。

第二档:单机 8 卡、大 MoE 模型、并发上来了。 值得考虑同机 PD 分离。AMD/vLLM 的实验给出了可比的证据:同样 8 张 MI300X,把 0–3 卡划给 prefill、4–7 卡划给 decode、KV 走 RDMA,在 Qwen3-235B-A22B-FP8、2000 token 输入 / 1000 token 输出、8 req/s 的条件下 goodput 提升 2.5 倍。注意这里的收益来源不是”更多硬件”,而是消除阶段互相干扰——同机也能拿到。

第三档:多机集群 + MoE 大模型 + 长上下文。 这一档才需要全套:PD 分离 + 大规模 EP + 分布式 KV 池 + 计算/通信重叠。DeepSeek 官方推理系统的部署口径可以当作参照系:

  • Prefill 池:路由专家 EP32、MLA 与共享专家 DP32,一个部署单元跨 4 节点,每卡承担 9 个路由专家 + 1 个共享专家;
  • Decode 池:路由专家 EP144、MLA 与共享专家 DP144,一个部署单元跨 18 节点,每卡承担 2 个路由专家 + 1 个共享专家;
  • 这个非对称本身就是 PD 分离的价值所在:同一个模型在两个池里的最优并行策略差了 4.5 倍(EP144 : EP32 = 144/32=4.5144/32 = 4.5)。注意这里说的是并行度配比的差异,不是整体性能差 4.5 倍——两池的总卡数本就不同(4 节点 vs 18 节点)。
  • 生产口径:24 小时内输入 608B token(其中 342B、即 56.3% 命中磁盘 KV 缓存)、输出 168B token;平均输出速度 20–22 token/s,平均每输出 token 对应的 KV 缓存长度 4,989 token;节点占用峰值 278 个、平均 226.75 个(每节点 8 张 H800);按每 GPU 小时 2 美元计,单日成本 87,072 美元。
  • 单节点产能:prefill 约 73.7k token/s 输入(含缓存命中),decode 约 14.8k token/s 输出。

成本账的落点:SGLang 用 96 张 H100 复现出的自部署口径是约 0.20 美元/百万输出 token,约为官方 API 的 1/5。这个差价不是营销话术,而是几个因子的乘积:PD 分离让两池各自满配、MLA 把 KV 压缩到 1/57(§4.2)、分布式 KV 池把 56.3% 的输入 token 从”重算”变成”读缓存”。每一层都在同样一批卡上多挤出一点有效吞吐(有效吞吐 / goodput 口径——见 §5.1 对 vLLM 那句反向声明的说明,它不等同于裸吞吐翻倍)。

然后收成一个可以直接拿去问框架的问题清单:

评估推理框架时该问的四个问题(顺序不能颠倒):

  1. 基础项齐了吗——continuous batching、paged attention、chunked prefill、prefix caching。这是「能不能跑」。
  2. PD 分离支持到什么成熟度——实验性(vLLM)、主路径(SGLang),还是产品化(NVIDIA Dynamo)。这是「第一个池跑得好不好」。
  3. MoE 的专家并行与通信重叠做到什么程度——支不支持大规模 EP、有没有 TBO / DualPipe 类的计算-通信重叠、有没有专家负载均衡(EPLB 这类)。这是第二层。
  4. AF 分离支持了吗——Attention/FFN 拆池有没有官方路径、要求什么配比与部署形态(vLLM AFD Plugin 目前是 experimental,非默认)。这是「要不要上更前沿的拆法」。

前三问没答好,问第四问没有意义。

十二、边界与未解

已经算清楚的部分:算术强度差异(2B/p2B/p)、平衡点(A∗=Rpeak/BWA^{*} = R_{\text{peak}}/BW)、KV 每 token 缓存公式与 MLA 的 57 倍、气泡比例 (P−1)/(m+P−1)(P-1)/(m+P-1)、AF 分离的 micro-batch 下界 m≥2(1+Tc/Tf)m \ge 2(1 + T_c/T_f)、KV 传输与 prefill 计算的常数比(本文推导约 1.9%)。这些都是可以拿计算器复核的。

以下部分是明确未解的,或者在公开材料里找不到确切口径的:

  1. DeepSeek 未公布 KV 传输在生产环境中的实际带宽利用率,也未公布 PD 分离交接点占 TTFT 的比例。本文 §5.2 的 1.9% 是纸面推导(假设网络与算力同时打满),不是实测值。
  2. Prefill 池与 Decode 池的最优配比没有「普适」答案,但论文给了一个明确的参照点。Mooncake 论文 §5.5 专门做了 P/D ratio 扫描:在 16 个 8×A800 节点上,把比例从 5P11D 逐步调到 11P5D(中间取 6P10D、7P9D、8P8D、9P7D、10P6D),阈值取 TTFT 10 秒 / TBT 100 毫秒,结论是当 P/D 比例约为 1:1 时有效请求容量最高,说明此时两个池的负载相对平衡;论文并说明线上流量的统计特征总体稳定,因此选择固定 P/D 比例、只在出现明显负载波动时切换节点角色。论文另指出 prefix caching 在 128k 输入长度下最多能把 TTFT 降低 86%。所以「≈1:1 最优」是这篇论文在自身硬件与负载下的结论,跨负载直接照搬同样不成立。
  3. 跨来源的吞吐数字不可直接横向比较。SGLang 主动声明 DeepSeek 官方 profile 的吞吐约为其生产环境的两倍。看到”某框架打平官方”的说法时,必须问它对比的是 profile 还是生产值。
  4. DualPipe 在推理侧的采用情况官方未公布。DeepSeek 的推理文档描述的是双批重叠与 5 阶段流水线,并非 DualPipe 本身;把两者混为一谈是常见的误读。
  5. AF 分离的工程复杂度与收益尚未在公开材料里形成共识。MegaScale-Infer 是系统论文(字节 Seed 与北大),其 1.90 倍是特定模型与硬件下的结果;vLLM 官方的 AFD 插件虽然已于 2026-07-23 发布,但官方自己标注为 experimental、需要更多跨硬件验证,而且其受控实测中 48A16F 这一配比相对 EP64 基线是负收益。准确表述是:AF 分离已经有官方实验性路径(非默认),但「该不该上、按什么配比上」仍没有通用答案。
  6. 稀疏度与专家负载不均衡的关系仍是开放问题。MegaScale-Infer 用到的是「按专家热度做设备内冗余放置」(on-device redundancy based on expert popularity),并未涉及 EPLB——EPLB(Expert Parallelism Load Balancer)是 DeepSeek 开源、SGLang 等框架采用的组件(采用冗余专家 + 启发式打包,SGLang 的 96×H100 部署即用到 EPLB 288 专家池),SGLang 也把继续优化列为后续方向。即便有这类机制,专家负载不均衡仍无法完全消除。
  7. 同机 PD 分离的收益边界尚不清晰。AMD 的 2.5 倍是在单一模型、单一负载画像下测得的;换模型(尤其是注意力结构不同、KV 尺寸差一个数量级的模型)收益会显著变化。
  8. chunk 尺寸的最优值依赖硬件瓦片与批组成,Sarathi-Serve 给出的 257 vs 256 差 32% 是一个具体例证,说明这里有实际调参空间,但不像 mm 那样有闭式解。

十三、小结

回到开头的直觉:Prefill 撞权重撞得狠,Decode 撞得轻,所以它们的算术强度差一个 batch 大小的倍数。 本文把这个直觉一路算到了具体的数字上:

  • 算术强度 A=2B/pA = 2B/p,bf16 下等于 batch 大小;H100 SXM 的平衡点 A∗≈295A^{*} \approx 295 FLOPs/Byte,因此 Decode 需要约 300 路并发才能把算力吃满(MegaScale-Infer 对 A100 给出的 156 是这个式子的另一个解)。
  • MLA 把 Attention 的算术强度抬高约 57 倍,同时把 KV 从 3.81 MiB/token 压到 68.6 KiB/token;落到并发上,是 214 路与 3.76 路的区别(十进制口径,比值 56.9)。
  • PD 分离之所以成立,是因为 KV 传输时间与 Prefill 计算时间的比值是个与上下文长度无关的常数(本文推导约 1.9%),而它换来的是两个池各自的最优并行度(DeepSeek 的 EP32 vs EP144,相差 4.5 倍)。
  • 剩余的空间与时间优化都归到同一句话:把通信藏进计算。气泡公式 (P−1)/(m+P−1)(P-1)/(m+P-1) 告诉你需要多少 micro-batch,AF 分离的下界 m≥2(1+Tc/Tf)m \ge 2(1+T_c/T_f) 告诉你拆分后最少要几份,DualPipe 则把前导因子砍半并让双向流水线互相填坑。

真正决定要不要上的,从来不是技术是否先进,而是:你的网络带宽够不够(§5.2 的常数比)、你的并发够不够(§3.3 的 300 路)、你的上下文够不够长(§4.4 的显存账)。 三个都不够,最该做的是把 continuous batching 与 prefix caching 做扎实;三个都够,才轮到 PD 分离与 AF 分离登场。

📋 来源与核验记录

本文的论文与官方文档数字均来自以下一手来源,逐条在写作时打开复核;文中的推导均由这些来源的硬件/架构参数算出,已与来源数据分开标注;另有两条站内条目口径(厂商口径 / 推算值)单独标明,见文末。

一手来源:

  • DeepSeek-V3 技术报告(671B/37B、14.8T 预训练 token、2.788M H800 GPU 小时、16 路 PP / 64 路 EP / ZeRO-1 DP、计算与通信比约 1:1、NVLink 160 GB/s 与 IB 50 GB/s、20 SM / 10 通信通道、DualPipe chunk 四块拆分、61 层 / 隐藏维 7168 / n_h = d_h = 128 / d_c = 512 / d_c’ = 1536 / d_h_R = 64 / 256 路由专家激活 8 个):https://arxiv.org/abs/2412.19437
  • DeepSeek-V3 技术报告 HTML 全文(用于逐句复核 §3.2.1、§3.2.2 与超参数一节):https://arxiv.org/html/2412.19437v1
  • DeepSeek 官方 DualPipe 仓库 README(1F1B / ZB1P / DualPipe / DualPipeV 的气泡公式、参数副本 1×/2×、激活占用 PP / PP+1、设备数 PP / PP/2;8 个 PP rank 与 20 个 micro-batch 的调度示例):https://github.com/deepseek-ai/DualPipe/blob/main/README.md
  • DeepSeek 官方推理系统概览(OpenSourceWeek Day 6;prefill EP32/DP32 跨 4 节点、每卡 9 路由专家 + 1 共享专家;decode EP144/DP144 跨 18 节点、每卡 2 路由专家 + 1 共享专家;8/256 专家激活;prefill 双批重叠与 decode 5 阶段流水线;608B 输入 token / 342B 命中磁盘缓存(56.3%)/ 168B 输出 token;平均输出 20–22 token/s、平均 KV 长度 4,989 token;节点峰值 278、平均 226.75(每节点 8 H800);单日成本 87,072 美元按每 GPU 小时 2 美元计;prefill 约 73.7k token/s 输入、decode 约 14.8k token/s 输出):https://github.com/deepseek-ai/open-infra-index/blob/main/202502OpenSourceWeek/day_6_one_more_thing_deepseekV3R1_inference_system_overview.md
  • DeepSeek-V2 技术报告(Table 1 的每 token KV 缓存公式:MHA 2n_h·d_h·l、GQA 2n_g·d_h·l、MQA 2d_h·l、MLA (d_c + d_h_R)·l;d_c = 4d_h、d_h_R = d_h/2;相比 DeepSeek 67B 降低 KV 缓存 93.3%、最大生成吞吐 5.76 倍;236B 总参数 / 21B 激活):https://arxiv.org/html/2405.04434v4
  • DistServe 论文(arXiv 2024-01-18;PD 分离与 goodput 优化的早期奠基工作之一,OSDI 2024):https://arxiv.org/abs/2401.09670
  • Splitwise 论文(arXiv 2023-11-30,早于 DistServe 的 2024-01;阶段拆分到不同机器;token 生成阶段不需要最新一代 GPU 算力;2.35 倍吞吐同成本同功耗,或 1.4 倍吞吐 + 降低 20% 成本):https://arxiv.org/abs/2311.18677
  • Mooncake(FAST ‘25 / USENIX 正式版,Kimi 生产服务系统;Kimi 在 A800 与 H800 上分别多承接 115% 与 107% 请求;命中率最高比本地缓存高 2.36 倍、prefill 计算时间最多省 48%;有效请求容量提升 59%~498%;跨数千节点、每天超 1000 亿 token;3M token 本地缓存在多数负载下拿不到理论最高命中率的 50%,接近理论最高命中率需 50M token 容量即至少汇聚 20 个节点 DRAM;prefix caching 在 128k 输入下最多降 TTFT 86%;§5.5 的 P/D ratio 扫描:16 个 8×A800 节点上从 5P11D 经 6P10D/7P9D/8P8D/9P7D/10P6D 扫到 11P5D,TTFT/TBT 阈值取 10 s / 100 ms,结论为 P/D ≈ 1:1 时有效请求容量最高):https://www.usenix.org/system/files/fast25-qin.pdf
  • SGLang 官方博客《Deploying DeepSeek with PD Disaggregation and Large-Scale Expert Parallelism on 96 H100 GPUs》(12 节点 × 8 H100;52.3k 输入 token/s 与 22.3k 输出 token/s 每节点;约 0.20 美元/百万输出 token、约为官方 Chat API 的 1/5;输出吞吐相比朴素 TP 最多 5 倍;prefill 4 节点 EP32 在 1K/2K/4K 下 57,674 / 54,543 / 50,302 token/s、最多 3.3 倍于 TP16、与官方 profile 差 5.6%;decode 9 节点 EP72 为 22,282 token/s/节点、5.2 倍于 TP16,模拟 MTP 下 17,373 token/s/节点、低于官方 profile 6.6%;TBO 吞吐提升 27%~35%、朴素配置 8,192 token/device 即 OOM 而 TBO 可到 16,384 token/device、综合提升 40.5%;EPLB 288 专家池;明确声明官方 profile 吞吐约为其生产环境的两倍):https://www.lmsys.org/blog/2025-05-05-large-scale-ep/
  • vLLM 官方文档《Disaggregated Prefilling (experimental)》(分离的两条动机:分别调 TTFT 与 ITL、控制尾部 ITL;标注为 experimental;同页加粗声明「Disaggregated prefill DOES NOT improve throughput」):https://docs.vllm.ai/en/latest/features/disagg_prefill
  • vLLM 官方博客《Announcing vLLM AFD Plugin: Disaggregating Attention and FFN for Flexible MoE Serving》(2026-07-23 发布;experimental 外部插件,经 vllm.general_plugins 入口接入、无需改 vLLM 源码;支持 NVIDIA GPU 与昇腾 NPU;同步 P2pNccl/CAMP2p 与异步 CAMAsync connector;DeepSeek V2/V3 系(含 V3.2)与 GLM MoE 模型包装器;DBO 需恰好 2 个 ubatch;DeepSeek-V3.2 W8A8 on Ascend 910C 受控实测:16K 输入下 64A16F 相对 EP64 +11.3%、48A16F -5.3%,32K 输入下 +9.0% / -10.0%;CAM async prefill 实验 12 req/s 下中位 TTFT 15.1 s → 8.0 s):https://vllm.ai/blog/2026-07-23-vllm-afd-plugin
  • vLLM AFD Plugin 官方仓库(实现范围与路线图:模型 runner v1 only、decode-only graph、双 ubatch、硬件门控的端到端测试):https://github.com/vllm-project/afd-plugin
  • DeepSeek 官方 EPLB 仓库(Expert Parallelism Load Balancer:冗余专家 + 启发式打包,来自 DeepSeek-V3 论文的专家冗余策略;与 MegaScale-Infer 的按热度冗余放置不是同一件事):https://github.com/deepseek-ai/EPLB
  • vLLM 官方博客《Next-Level Inference: Why Your Single-Node vLLM Setup Needs Prefill-Decode Disaggregation》(AMD MORI-IO;单节点 8 卡 MI300X,0–3 卡 prefill、4–7 卡 decode;Qwen3-235B-A22B-FP8、2000 token 输入 / 1000 token 输出、8 req/s;同卡数下 goodput 2.5 倍;KV 传输量可达数 GB;read/write 两种模式;RDMA 传输):https://vllm.ai/blog/2026-04-07-moriio-kv-connector
  • NVIDIA 官方技术博客《How NVIDIA GB200 NVL72 and NVIDIA Dynamo Boost Inference Performance for MoE Models》(分离部署给 DeepSeek R1 带来中等延迟区间 6 倍吞吐;Dynamo 负责 KV 传输、请求路由与动态 rate matching;GB200 NVL72 的 NVLink 域连接最多 72 张 Blackwell、每 GPU 1.8 TB/s;Llama 70B 同区间最多 3 倍):https://developer.nvidia.com/blog/how-nvidia-gb200-nvl72-and-nvidia-dynamo-boost-inference-performance-for-moe-models
  • NVIDIA 官方技术博客《Introducing NVIDIA Dynamo》(分离 prefill/decode 推理阶段、LLM-aware 路由、GPU 间异步数据传输;prefill 计算受限、decode 内存受限;四大组件含 NIXL 传输库与 KV-aware 路由):https://developer.nvidia.com/blog/introducing-nvidia-dynamo-a-low-latency-distributed-inference-framework-for-scaling-reasoning-ai-models
  • NVIDIA H100 Tensor Core GPU 官方规格页(H100 SXM:bf16 Tensor Core 1,979 TFLOPS 含稀疏、不含稀疏减半即约 989 TFLOPS;fp8 3,958 / 稠密 1,979 TFLOPS;显存 80GB;显存带宽 3.35 TB/s;NVLink 900GB/s;TDP 最高 700W):https://www.nvidia.com/en-us/data-center/h100/
  • Sarathi-Serve 论文(chunked-prefills 与 stall-free batching;朴素混合批会让 TBT 延迟最多涨 28.3 倍;chunk 257 相比 256 使 prefill 时间增加 32%;线性层执行时间在 batch 128–512 token 区间基本持平、prefill 约 512 token 即饱和;吞吐提升单卡 Mistral-7B 最多 2.6 倍、8 卡 Falcon-180B 最多 6.9 倍):https://arxiv.org/html/2403.02310v1
  • MegaScale-Infer 论文(AF 分离 / disaggregated expert parallelism;ping-pong 流水线的 micro-batch 下界 m ≥ 2(1 + T_c/T_f)、0 < T_c/T_f < 1;A100 上 batch 至少 156 token = 312 TFLOPS / 2 TB/s;156 × topk2 / 8 专家 = 39 token/专家,对应理论 MFU 上限 = top-k 除以专家数 = 2/8 = 25%;每 GPU 解码吞吐最多 1.90 倍;异构集群每美元吞吐 1.7 倍;M2N 通信相比 NCCL 吞吐 4.2 倍、延迟低 68.2%):https://arxiv.org/html/2504.02263v1

本文自行推导(非来源数据,正文中已逐处标注,可复算):

  • 架构 61 层、nh=dh=128n_h = d_h = 128、dc=512d_c = 512、dhR=64d_h^{R} = 64 代入得 MLA 每 token KV = 70,272 B(68.6 KiB),MHA 反事实为 3,997,696 B(3.81 MiB),比值 56.9。
  • DeepSeek-V3 权重按 fp8 计 671 GB;EP144 每卡分摊约 4.7 GB;75 GB 可用显存 ÷ 350.6 MB/请求 ≈ 214 路并发(MHA 反事实 3.76 路,十进制口径;二进制口径为 4.04 路;214 / 3.76 ≈ 56.9,与 KV 比值自洽)。
  • A∗=989 TFLOPS/3.35 TB/s≈295A^{*} = 989\ \text{TFLOPS} / 3.35\ \text{TB/s} \approx 295;bf16 下解码需约 295 路并发才能把算力吃满;Decode 的算术强度 1 对平衡点 295 ⇒ 算力利用率上限约 0.3%。
  • 1F1B 气泡比例 (P−1)/(m+P−1)(P-1)/(m+P-1) 在 P=16P = 16 下:m = 16 为 48.4%、m = 32 为 31.9%、m = 64 为 19.0%、m = 128 为 10.5%、m = 256 为 5.5%;由此得「要把气泡压到 10% 以下需要 m > 9(P−1)(P = 16 时 ≈136 ≈ 8.5P)」。
  • KV 传输与 prefill 计算时间的比值约 1.9%(以 50 GB/s 网络、989 TFLOPS、37B 激活参数计),与上下文长度无关。
  • 32K 上下文的 KV 传输时间 46.0 ms(按 50 GB/s)与 14.4 ms(按 160 GB/s)。

未能核实的点(如实列出):

  • DeepSeek 官方未公布 KV 传输在生产中的实际带宽利用率,也未公布交接点占 TTFT 的比例;§5.2 的 1.9% 是纸面推导。
  • DeepSeek 未公布推理侧对 DualPipe 本体的采用情况;其推理文档描述的是双批重叠与 5 阶段流水线。
  • 本文未给出「Prefill 池 : Decode 池」的推荐配比——公开材料一致表明它随负载变化(Mooncake 专门做了 P/D 扫描),给出固定比例会是编造。
  • AF 分离已有 vLLM 官方实验性插件(2026-07-23 发布),但其官方定位是 experimental、非默认路径,且官方自测中 Attention/FFN 配比不当会出现负收益;因此本文把它写成「有官方实验性路径,但远未成为业界默认做法」。
  • 「Kimi 缓存命中率约 90%」与「K3 需 8×A100/H100 起步」两条均为站内条目口径,不是 Mooncake 论文或 Moonshot 官方文档的原文:前者是厂商口径(本站 Kimi K3 条目 记录,论文未公布该数字),后者站内自己标注为推算值(非官方建议)。本文已按此口径恢复这两条并逐处标明来源与性质,未把它们混入论文数据。