八卡异构集群设计台
章首给定:一台服务器有 4 张 A100 80GB SXM,另一台有 4 张 H20 96GB,两台之间没有 NVLink,只有一张 200 Gbit/s RDMA 网卡(按 25 GB/s 计)。模型是 Qwen3-8B,权重和 KV 都用 BF16。每秒到达 3.5 个请求,每个请求输入 8192 个 token、输出 1025 个 token(带思考过程)。一张卡就能装下整个模型,所以一张卡就是一个 worker。
可以点下面六个书中情景,也可以自己拖参数,或者直接点配比热力图里的格子。
按 Roofline 算:P 受算力限制,D 每步给 batch 内 32 条请求各生成 1 个 token,平均上下文取 L + (G−1)/2,读权重 + KV,受显存带宽限制。效率 50% 是书中的校准值。
计算与状态的分布方式
先分清硬件组织和服务组织。进程跑在加速器或 CPU 上,通信组里每个进程有一个 rank;多个进程可以合起来组成一个推理实例。完整服务副本拥有完成整个模型推理所需的全部权重和执行能力,可以独立接收请求。本章用 P 表示 prefill,D 表示 decode;P、D 由同一组资源执行称为共置。
多卡共同执行
八张卡组成一个协作组,处理同一批请求。
完整副本
每个副本都能完成整次推理,副本本身也可以由多张卡组成。
PD:按阶段分
两个服务池分别调度,P 把上下文 KV 交给 D。
AF:按层内算子分
注意力一侧产生激活交给 FFN 一侧,结果再送回。
四种方式改的是系统的不同部分:副本改请求分给谁,PD 改阶段在哪执行,AF 改算子在哪执行,共享 KV 改状态能被谁读到。它们可以一项一项加,也可以组合。
| 部署方式 | 想得到的收益 | 新增的主要约束 |
|---|---|---|
| 增加完整副本 | 处理更多独立请求,分散排队 | 模型复制、缓存分散、启动并维持实例 |
| PD 分离 | 两个阶段分别配置计算能力 | KV 交接、两端同时占内存、两个队列 |
| AF 分离 | 让算子用上合适的计算与存储资源 | 逐层激活往返、同步、流水各段负载均衡 |
| 共享 KV | 跨实例复用上下文,少做重复 prefill | 缓存标识、读取、就绪通知、失效与空间释放 |
容量判据:λ·dr < nr
每个请求在资源 r 上占用 dr 秒,这类资源有 nr 个能独立工作的单元。同一资源上的多项操作先把时间加起来;用不同资源的操作,各列一条约束。N 个相同共置副本的上限是 μco = N / (dP + dD)。
GPU 秒够不够
书例:4 请求/s × 0.5 GPU 秒 = 2 张卡持续工作λd 恰好等于 n 时,卡全部忙于处理后续请求,一次突发带来的积压永远消不掉;只有留出余量才能消化突发。
同一请求的执行路径与状态驻留
沿一条多轮请求的时间线看:有视觉输入时,E 先把图像编码成特征,编码结果 EC 可以复用;P 处理输入,D 逐步生成;调用工具时计算暂停,返回后新一轮 P 再处理新增信息。权重跨请求常驻,激活只在相邻算子间传,KV 随已处理的位置增长。
图 9-5 · 计算停了,状态还在
阶段宽度只表示先后顺序,不代表实际时长;EC 只在有视觉输入时出现。
1025 个输出,只有 1024 次 decode
P 算出最后一个输入 token 的 logits,采样出第 1 个输出;之后 G−1 = 1024 次 decode 依次处理前 1024 个输出。这时 KV 连续覆盖 8192 + 1024 = 9216 个 token,最后返回的第 1025 个 token 还没送进模型。下一轮从这里接着算:先处理这个 token 和新增输入。
多卡副本的状态也会复制:Qwen3-235B-A22B 的 TP2×EP4 部署用 8 张卡处理同一批请求,注意力和 KV 在 4 个 EP 组里各存一份,一条 8192 token 请求的上下文在实例内占 5.875 GiB,是单份逻辑 KV 的 4 倍。要增加能独立接请求的副本,还得另配一套完整权重与状态。
Prefill–Decode 分离与资源配比
Prefill 一次处理很多新 token,大矩阵乘能充分复用权重;decode 每步每请求通常只处理一个 token,要反复读权重和上下文。混在一起跑时,长 prefill 会推迟在途请求的下一个输出,过分优先 decode 又让新请求等得更久。PD 分离(DistServe、Splitwise 等系统)把两个阶段放进不同服务池,各有自己的队列、batch 和资源配比。
两个池都要完整权重,因为每个阶段都要跑完整的前向计算;要交接的是 KV。分离带来的收益首先要抵得过这次交接。
KV 有多大,传多久
GQA:VKV = 2·n·L·hkv·dh·b MLA:VKV,MLA = n·L·(dc + dr)·b
例 9.1 · KV 交接需要多久
启动与同步 5 μs| 交接状态 | 每 token | 8192 token | 25 GB/s | 50 GB/s |
|---|---|---|---|---|
| Qwen3-8B,GQA | 144 KiB | 1.125 GiB | 48.3 ms | 24.2 ms |
| DeepSeek-V3,紧凑 MLA | 68.6 KiB | 549 MiB | 23.0 ms | 11.5 ms |
MLA 只存上投影之前的潜变量,上投影按结合律挪到查询一侧去算。如果把 DeepSeek-V3 的 128 个头展开保存,每 token 约 4.77 MiB,是紧凑表示的 71 倍;紧凑 MLA 也只有 Qwen3-8B GQA 的 0.48 倍。整份交接时 5 μs 启动只占万分之一,提高带宽更有用。
图 9-6 ~ 9-8 · 整份双缓冲交接的三个时刻
分块传输时,目的端确认收到一块,源端就能提前释放这一块,缩短两端重复驻留的时间;经主存中转则依次占用源端、主存和目的端缓冲,主存到 GPU 的拷贝成了新的依赖。
链路既限每秒能交接几份,也定每份要等多久
100 GbE 每方向 12.5 GB/s传输时间决定单个请求至少等多久;到达速率与传输速率之差决定队列长多快。同一个 100 GbE 端口:GQA 下每秒 16 次会持续积压,换成 MLA 就够用。模型换了上下文表示,同一条链路的结论就可能翻转。
两种卡强弱正好相反
| 卡 | BF16 稠密算力 | 显存带宽 | 显存 | 按 50% 计的有效值 |
|---|---|---|---|---|
| A100 80GB SXM | 312 TFLOP/s | 2039 GB/s | 80 GB | 156 TFLOP/s · 1020 GB/s |
| H20 SXM5 96GB | 148 TFLOP/s | 4096 GB/s | 96 GB | 74 TFLOP/s · 2048 GB/s |
Prefill 8192 token 要做 133.6 TFLOPs 矩阵运算,只读约 15 GB 权重,受算力限制。Decode 一步给 32 条请求各出一个 token,平均上下文 8704,读约 15.1 GB 权重加 41.1 GB KV,运算只有 0.65 TFLOPs,受带宽限制。效率取 50%:第 8.6.3 节实测 decode 带宽效率在 batch 32 插值约 49%,prefill 算力效率 58%–62%。另一半能力去了哪里:没计入的工作(tile 补齐的零行、没重叠的通信)和可以去掉的主机开销(逐个提交 kernel、重建通信组与执行图)。
每请求占用的 GPU 秒
8192 输入 · 1025 输出A100 的 prefill 比 H20 快一倍多,H20 的 decode 比 A100 快一倍。共置时每张卡都得两段都做:A100 每请求 2.62 GPU 秒,H20 2.68,八张合计 3.02 请求/s,比到达率少约 0.5 请求/s。
同构八张 A100:分离换的是延迟稳定,不是吞吐
共置时每卡每请求 0.856 + 1.764 = 2.62 GPU 秒,八张合计 3.05 请求/s。分离只能按整卡划分:3 张 P 给 3.50,5 张 D 给 2.83,上限 2.83,比共置低 7%。每个请求消耗的 GPU 秒没有变,整数划分又让多出的能力只能闲着。
一次 8192 token 的 prefill 插进来时
A100 一步 decode 访存 55.1 ms,矩阵计算只用 4.2 ms,空闲算力够处理约 490 个 prefill token;8192 个 token 分 17 块,捎带在 17 个 decode 步里,在途请求的输出间隔不变。能藏住多少要用实测的混合步时间判断。所以同构集群一般先用分块 prefill;分离的价值在于两阶段能各选并行方式和 batch,并彻底隔开排队。示意图中 KV 交接按 25 GB/s 画出 48 ms。
异构集群:配比决定上限
μPD = min( μP, μD, Bnet / VKV ) = min(4.67, 4.55, 20.7) ≈ 4.55 请求/s
分离后两类卡都避开了自己慢的那个阶段,上限从 3.02 升到 4.55,是共置的 1.51 倍。模型做的工作一点没少,变的是谁来做。角色对调后 P 池只剩 2.22。H20 一步 decode 的空闲算力只够约 85 个 prefill token,按理想捎带算,异构共置上限 4.17,仍低于分离:异构的收益来自硬件差异,分块替代不了。
偏离最优配比
一张 A100 从 P 调到 D:P 4.67 → 3.50,D 4.55 → 5.12,结果被 P 限到 3.50。一张 H20 从 D 调到 P:结果 3.42。最优配比让两池能力接近相等,一个池再富余也帮不了另一个池。
链路什么时候成为约束
条件是 Bnet < μ·VKV。在 4.55 请求/s 下,GQA 状态要求链路至少约 5.5 GB/s,紧凑 MLA 约 2.6 GB/s。高于这个值再加带宽,上限不变;低于它,热力图里所有高于 B/V 的格子都会被压平。
紧凑 MLA 省字节,不省全部工作
上投影挪到查询侧:每请求每步多 2.05 GFLOPs,H20 上 27.7 μs,1024 步 28.3 ms。D 池每请求 0.878 → 0.907 GPU 秒,能力 4.55 → 4.41,仍够。每步额外计算超过约 258 μs 才需要第五张 D 卡。
紧凑 MLA 的额外计算会不会压垮 D 池
换成紧凑 MLA 后,每 token 读取从展开的 4.77 MiB 降到 68.6 KiB,计算项却随 batch 增长,D 实例在更小的 batch 上就会从读取受限变成计算受限;例 9.2 的 rD 是按 batch 32 推的,要按新的转折 batch 重算。
请求组成一变,最优分工就变
图 9-11 · 同一组卡,三种请求
点击可载入设计台最适合的 P 卡数分别是 4、2、7。前缀命中减少 P 的新工作,把卡推向 D(这里假定 D 没有缓存,仍要交接完整 1.125 GiB);输出变短减少 D 的重复工作,把卡推向 P。输出 129 时共置已有 5.84,分离只多 8.5%。推理请求输出越长,带宽强、算力弱的 H20 越值钱。
调度分两个时间尺度:请求到达时选进哪个队列,决定眼前等多久;负载分布变化时调整池的规模,决定积压能不能长期消退。
Attention–FFN 分离与异构执行
AF 在模型层内部切分:注意力产生隐状态,FFN 或被选中的专家处理它,再把结果送回。下一层通常要等这个结果,所以小数据量传输的启动和同步会重复很多次。MoE 特别适合这种分工:专家总权重很大,每个 token 却只用其中几个。
路径一:搬权重到 GPU
路径二:CPU 就地算(KTransformers)
选哪条路取决于本批分给同一个专家的 token 数 m:这些行共用一份专家权重,m 越大,搬一次权重的代价摊得越薄,CPU 的算力却越早用完。
TC(m) = 2α + 2mhb/BL + max(2mPe/CC, We/BD) TG(m) = α + We/BL + max(2mPe/CG, We/BH)
例 9.3 / 图 9-14 · 八个专家放 CPU 还是 GPU
Qwen3-235B-A22B 专家 3×4096×1536 · BF16 36 MiB实验机:两颗 Xeon Platinum 8452Y(实测同插槽 220 GB/s、跨插槽 125 GB/s),PyTorch AVX-512 kernel 最高 1.8 TFLOP/s,KTransformers AMX kernel 最高 21.3 TFLOP/s;A100 40GB PCIe 按峰值 50% 计为 156 TFLOP/s、778 GB/s;PCIe 4.0 x16 交接按 25 GB/s、每次启动 5 μs。八个专家依次执行,未计格式转换。下方条形是 CPU 路径的两项:粗框那项较长,就是下界。用 AVX-512 时计算远长于读取,内存放在哪个插槽无所谓;换成 AMX,跨插槽读取反而成了长的一项。
装得下不等于来得及
每层常驻多少专家
每层 128 专家共 4.5 GiB · 94 层A100 80GB 全部给专家也只有约 74.5 GiB。容量选择直接改变执行路径:少驻留一些,就有更多专家交给主存一侧去算。
一个 batch 会碰到多少专家
E[U] = E·[1 − (1 − K/E)M]64 个 token 各选 8 个专家,共 512 次分派。均匀铺满 128 个专家时每专家 4 行,集中在 8 个专家时每专家 64 行;两种情况有效计算量都是约 19.3 GFLOPs,但权重读取分别是 4.5 GiB 和 288 MiB,在 220 GB/s 上约 22.0 ms 与 1.37 ms,差一个数量级。大主存、少 GPU 的服务器适合每专家行数少的负载:DeepSeek V4-Flash 单张 RTX 5090 配置要求至少 200 GB 主存,Kimi K2 的 Q4_K_M 配置约 600 GB。并发一高,瓶颈会从读权重转到 CPU 矩阵计算。
跨机 AF:专家分离与 All-to-All
把路由专家放进独立的专家池,保留注意力和 KV 的 worker 发送激活、接收结果,称为专家分离(EP 分离)。以两台 HGX H100 为例,一层 MoE 依次走四步:A 卡算完注意力并路由(每 token 选 8 个专家)→ dispatch:按专家所在卡分组发往 B 卡 → B 卡按专家重排、做矩阵乘 → combine:结果送回原 A 卡,凑齐 8 份后加权求和。
图 9-16 · 一层 MoE 的两次 4×4 All-to-All
两处等待:B 卡要等各来源的输入到齐才开算,A 卡要等一个 token 的全部专家输出返回才能求和。一张 B 卡收得多、算得慢,会同时拖住自己和所有等它结果的 A 卡。方块数量为示意。
大 EP 不自动加大 batch
n 个 token、每个选 k 个、共 E 个专家,每专家平均 n·k/E 行。n=1024、k=8、E=256 时是 32 行;把 256 个专家从 32 张卡摊到 128 张卡,平均还是 32 行,只是每卡专家变少了。
EP 组 ≠ 副本
只有多个 EP 组各存一整套专家时,它们才是能分别接任务的副本。只加保存部分专家的卡,请求绕不开繁忙的专家。共享专家池的队列、显存、版本和接纳策略要当整体管。
实证:MegaScale-Infer
2025 年论文,Scaled-MoE(317B)在 8 节点 × 8 张 80 GB Ampere 上,TPOT ≤ 150 ms 约束下每 GPU decode 吞吐达 TensorRT-LLM 的 1.90×。这包含放置、并行、流水与通信库的合力,不是“只开 EP 分离”的通用加速比。
图 9-17 · micro-batch 在两类节点间交错流水
理想流水 = tA + tF + (q−1)·max(tA, tF),忽略交接。拆小 micro-batch 让每段变慢、或者藏不住的往返通信超过节省量,收益就没了。
例 9.4 · AF 逐层交接 vs PD 一次交接
Qwen3-8B 的 36 层 FFN 放到另一侧,每层发一个 4096 维 BF16 隐状态(8192 bytes)并收回同样大小的结果:一步 decode 共 72 次、576 KiB。25 GB/s 下纯载荷 23.6 μs,72 次 5 μs 启动 360 μs,串行约 0.384 ms。
VKV/B + α = VAF/B + 72α ⟹ α* = (VKV − VAF) / (71·B)
图 9-18 · 启动开销决定谁更快
单看一步,5 μs 启动远低于四个临界值,AF 更快;放到整条请求上,PD 只交一次,AF 每步都交,隐状态宽度与 KV 表示无关,MLA 一个字节也省不了。prefill 的 8192 token 若也按整批稠密 AF 交接,激活载荷 4.5 GiB,约 193 ms。PD 先受大块 KV 搬移影响,AF 更怕小消息的启动开销和操作间依赖。
专家放置、复制与负载均衡
集中复用减少了权重读取,但热点专家都在同一张卡上时,别的卡帮不上忙。卡 r 完成的时间至少是 max(Fr/Cr, Wr/Br),合并结果要等最慢的那张。
决定完成时刻的是最长的那条横条,不是八条的平均。集中路由把要读的权重从 4.5 GiB 降到 288 MiB,却可能让最忙卡的计算量变成八倍:读取受限时有利,计算受限时有害。先找瓶颈,再决定追求复用还是分散工作。
图 9-19 / 9-20 · 512 次分派,均分 vs 全落卡 0
HGX H100,每张按 BF16 稠密峰值 989.4 TFLOP/s 的 50% 计为 494.7 TFLOP/s,只看专家矩阵计算。
EP 越大,skew 越大
沿用 n=1024、k=8、E=256(DeepSeek-V3 每层也是 256 个路由专家、每 token 选 8 个):一批 8192 次分派,平均每专家 32 行。设专家 0 是热点,收到平均值的倍数为下方滑块,其余行均分给另外 255 个专家,256 个专家按编号均分到各卡。
图 9-21 / 9-22 · 同一个热点专家在不同 EP 规模下
左:卡 0、1、2 和最后一张卡的行数 ÷ 每卡平均,每段是卡上的一个专家,橙色是热点。右:橙线为热点情形(可手算);蓝线为均匀随机路由、无热点时最忙卡 ÷ 平均,由本页用固定种子模拟 200 批得到(书中为 1000 批:EP8 约 1.04,EP256 约 1.52)。DeepSeek 公开的 decode 部署是 EP144、每卡 2 个路由专家,正在曲线右端附近,所以它加了 32 个冗余专家并按负载调整副本。
skew 至少分三层看:逻辑专家的选择频率决定每个专家的有效行数;放置与副本把行数变成每卡负载;token 的来源、目标和网络路径再把每卡负载变成每个方向的流量。专家热度不均未必造成卡间不均,卡间计算均匀也未必让链路均匀。另外,通信量还取决于 token 最初在哪:TP2×EP4 布局里各 EP 组已持有相同输入,跨组 dispatch 可以为零,只剩结果合并。
sexpert = maxj mj / (n·k/R) TX ≥ max( maxi ΣjVij/Bsendi, maxj ΣiVij/Brecvj, max𝒞 V𝒞/B𝒞 )
例 9.5 · 总通信量相同,热点让两次交换都变慢
1024 token × 8 专家 · 8 KiB 向量 · 每卡 ConnectX-7 50 GB/s最后一列是三段整批屏障下界之和,暂不计权重读取、padding、启动和排队。跨服务器时两次交换占八成:H100 算一份专家任务约 76 ns,网卡传一份 8 KiB 激活却要约 164 ns。热点分散后若两池之间只剩一条 400 Gbit/s 链路,仍要 1.342 ms,说明加专家卡替代不了跨池带宽;放进同一台 HGX 后,热点卡 0.391 ms 的计算成了最长段,这时该减热点卡的计算。
专家副本:先算显存,再算回本
同一逻辑专家有多个物理副本,调度器把任务分给副本。只要权重相同、路由权重用对、合并无误,就不必改 top-k 规则(改专家选择会改变模型行为,要分开评价)。vLLM、SGLang 的 EPLB 按路由统计调整副本位置。每卡每层加一个 36 MiB 专家,94 层要 3.30 GiB;只给最挤的 8 层各加一个,只要 288 MiB,相差近 12 倍。CRAFT 正是按层分配副本显存,在 DeepSeek-R1、Kimi K2 上端到端吞吐平均为对照的 1.14 倍、最高 1.2 倍。
例 9.6 / 图 9-24 · 热点要持续多少批,副本才回本
128 token 全选卡 0 上 8 个热点专家 · 复制 7 个到卡 1–7卡 0 每批要读写约 921 MB,受显存带宽(1675 GB/s 有效)限制;复制后只剩 576 次分派,每批 0.550 → 0.309 ms,省约 0.240 ms。七份副本依次发出,每份另计 5 μs 启动。Nmin = ⌊Tcopy/Δt⌋ + 1。跨服务器复制一次 5.32 ms,频繁跟着热点迁移会一直回不了本;同机复制几乎不受时间约束,限制它的是每张卡还能腾出多少显存。
多来源排队
多个 attention worker 可能同时选中同一个热点专家,各自小 batch 看着均衡,汇合后可能超出该专家的能力。稳定运行至少要 λ·E[Fj] < Cj、λ·E[Vℓ] < Bℓ;平均满足只是必要条件,突发和重尾仍会排长队。共享池能平滑波动,也可能放大相关热点。
副本放哪、怎么换
放到计算和带宽都有余量的位置。8 KiB(FP8 为 4 KiB)消息远大于 50 GB/s 网卡约 0.93 KB 的交点,先耗尽的是带宽而不是发起速率。保留当前 batch 的路由映射直到 combine 完成,迁移或回收旧副本前排空在途任务;给热点设接纳额度、限单个来源的在途量。丢 token、改 top-k、换专家都会改模型行为,不算透明均衡。
补齐与重叠
Grouped GEMM 的 tile 补齐
硬件算的是补齐后的矩阵,零行没有对应的真实 token。补齐和争用是 MFU 达不到峰值的两大来源,都出在实现层。
图 9-27 · 一个 token 等最慢的分支
Tt = maxe∈ℰ(t) Lt,e + Tmerge。时长为书中的教学值。整批屏障让没选中慢专家的 token 也一起等;逐 token 推进才能让它们先走。
图 9-25 / 9-26 · 分派、计算、合并三段流水
取例 9.5 跨服务器均衡分布:0.336 / 0.156 / 0.336 ms,串行 0.827 ms。两个 micro-batch 理想流水为 0.581 ms,节奏由网卡决定。通信各慢约 49% 或计算慢到 3.1 倍,收益就抵消了。第一批的 dispatch 填流水、最后一批的 combine 收尾,是流水之外的串行时间。比较通信库(NCCL、DeepEP V1/V2)时要固定版本、形状、精度和拓扑,记录字节数、GEMM 行数、padding、各阶段就绪/完成事件,再看层和请求耗时的 p50/p99。
KV 的分布、共享与请求路由
另一种省计算的办法:后续请求直接用前面算好的 KV。但“文本相同”不足以确定状态可复用。缓存键要沿前缀链标识出生成这份状态的整个计算:
同样的 token 配不同 adapter,投影出的 K、V 不同;同样的后缀接在不同前文后,注意力看到的上下文也不同。
图 9-28 · 目录用来找,对象用来算
路由器拿到的缓存事件通常只有位置和标识,不带 KV。事件遗漏、延迟或空间被释放,都会让记录的位置失效。
容量相加 ≠ 共享缓存
两个实例各有 4 GiB 私有主机缓存,同一份 1.125 GiB 前缀会各存一份,共占 2.25 GiB,谁也用不了对方那份。接到同一个共享存储后端,一份对象能服务两边,但生成前可能还要取回本地。SGLang HiCache、vLLM 多级缓存、LMCache 是不同的组织方式;取回是否经过 CPU 决定路径时间。
多级存储:放哪一级都比重算快
DGX A100:8 张 A100 80GB、2 TB 主机内存、8 块 3.84 TB NVMe(Solidigm D7-P5520,顺序读 7.1 GB/s、写 4.2 GB/s)、8 张 200 Gbit/s 网卡,按每张 GPU 分到的一份算;对象是 Qwen3-8B 的 8192 token 前缀,1.125 GiB。
图 9-29 · 每张 A100 可用的四级存储
重算这份前缀约 856 msHBM 一栏是 80 GB 减 16.4 GB 权重的上限,未扣激活与工作区。远端取回先经网卡到主存,再经 PCIe 到 GPU,两段串行。真正的限制在别处:缓存能不能留到下次使用,读取能不能与计算重叠,写入各级要付多大代价。
图 9-30 · 要留多久,就要多大容量:C ≥ r·T
r ≈ 1.41 GB/s:A100 连续做无命中 8K prefill 产生 KV 的速率阿里云线上 trace:面向个人的对话负载 80% 复用在 10 分钟内,企业 API 负载 80% 在 10 秒内。按此估算,API 只需 14.1 GB,HBM 就够;对话要 846 GB,超过每卡主机内存,要加 SSD。同一研究按实例实际请求率估计(请求也更短),8 卡 A100 配 1 TB 主机内存已经够用,r 小得多。人工对话的间隔以分钟计,程序调用以秒计。
图 9-31 · 容量越大,命中率涨得越慢
Mooncake 公开的 Kimi 一小时采样 trace,每块 512 token,LRU 淘汰:1,000 块 30%,50,000 块(按 Qwen3-8B 约 3.77 TB)50%,容量不限也只有 51%。超过一半的块从未被再次使用;阿里云 trace 里 10% 的块贡献了 77% 的复用。图中只标书里给出的点。
取回一次 vs 每步都远程读
25 GB/s 网卡。每步都远程读一份不变的前缀,并行安排也传不完;状态减半只把倍数减半。取回一次后驻留,把传输从“每步一次”降到“每次复用一次”,代价是本地 HBM 的容量×时间(字节·秒)。不活跃的会话放远端,恢复时取回。
保存再取回,何时比重算快:Twrite + k·Tread < k·Trecompute
临界带宽 1.41 GB/s 恰好就是 KV 产生速率 r:取回 V 字节要 V/B,重算要 V/r。带宽在 1.41–2.82 GB/s 之间要复用至少两次才回本;10 GbE(1.25 GB/s)取回一次就要约 966 ms,应重算或把取回挪出关键路径。本地 SSD 写约 288 ms、读约 170 ms,复用一次合计 458 ms,仍少于 856 ms。
让读取与计算重叠
命中后只算 256 个新 token,约 30.9 ms。CachedAttention 逐层预加载:第 i 层只用第 i 层的 KV,GPU 算第 i 层时 PCIe 读后面的层。Qwen3-8B 每层历史 KV 32 MiB。读取比计算多出的那部分字节,就要靠请求开始前(利用上一个 batch 的执行时间)先读进 HBM 缓冲:
Sbuf = B·(Tread − Tnew) = 25 GB/s × (48.3 − 30.9) ms ≈ 437 MB ≈ 14 层
图 9-32 ~ 9-34 · 整份读入、逐层预加载、提前读入
新输入达到约 400 token,计算就能掩盖从主机内存的读取;远端串行路径约 800,本地 SSD 约 1400。CachedAttention 在 LLaMA-13B 上实测:1K 历史、100 新 token 时,逐层预加载让 prefill 缩短 35%,再加 15 层缓冲后缩短 61%。
图 9-35 · 利用排队时间从 SSD 预取
从 SSD 读一层 4.73 ms,是计算一层的 5.5 倍,逐层预加载掩盖不了。请求还在排队时,调度器已经知道它要哪份前缀,可以先从 SSD 读进主机内存;排队不短于 170 ms,这次读取就不在关键路径上。换出时也看队列:下次使用最晚的先换出。CachedAttention 回放 ShareGPT:按队列预取/换出总命中率 86%(99.6% 以上来自主机内存),LRU 58%、FIFO 48%,几乎每次命中都要读 SSD。256 GiB 主机内存约可容纳 227 份 8K 前缀。
SSD 的限制是写入寿命
D7-P5520 · 5 年 1 DWPD以 1.41 GB/s 写入只占 PCIe 的 5.6%、SSD 顺序写的 34%,带宽不是问题。全写进 SSD,5 年寿命不到两个月就耗尽。所以写入前先做准入:只写已被复用过的前缀,或还没结束的多轮会话。按额度写入时,SSD 恰好能存最近一天的 KV。同卡双引擎实验:12 次复用机会里,4 GiB 共享 CPU 池完整命中 5 次,8 GiB 池 12 次。
持久化与部分重算
持久化让状态在重启或暂停后仍可用:完整保存少重算,周期 checkpoint 少写入但恢复多做,部分重算用保留的前缀补齐缺口。Qwen3-8B 一个 16 token 的逻辑页是 2.25 MiB;按 36 层 K、V 分开是 72 个 32 KiB 小段,容易受每秒操作数限制;按页汇集成一个 2.25 MiB 对象,时间更多花在连续载荷上。
图 9-36 · 读入 64 页,用上 63 页
只有匹配成功、能连续接上已有上下文的页才能替代计算;磁盘再快,也改变不了要处理的末页。页面缺失时比较等待与重算:A100 重算 8192 token 约 0.856 s,为一个不可用对象已经等了 1 s,就已经超过整段重算。截断页实验里,无条件等待的请求 60 秒内一直没完成,允许放弃等待后靠重算得到结果;之后还要隔离或修复坏页。
缓存亲和性与请求路由
Tfirst = max(Q, R) + C Q:GPU 最早可执行时刻;R:状态就绪时刻;C:状态就绪后的剩余工作
依赖关系也算时间:Q = 80 ms、取回 60 ms、剩余计算 10 ms,取回与排队并行时共 90 ms;等 GPU 空了才开始取回则是 150 ms。工作量一样,差了 60 ms。
例 9.7 · 发给有缓存但排队的 A,还是空闲但没缓存的 B
8192 前缀 + 256 新 token · A100 156 TFLOP/sB 远端取回:查找 10 ms → 网络读到主存 → PCIe 25 GB/s 到 GPU,计算要等数据和 GPU 都就绪。提高远端带宽只缩短橙色段。重算 8448 token 约 138.4 TFLOPs、887 ms,几乎总是最慢;取回与重算打平的带宽只有约 1.48 GB/s。但每秒 16 次取回就要约 19.3 GB/s,占 25 GB/s 链路的 77%:单请求算完还要算持续流量。
缓存位置预测失准时
A 排队改为 80 msE[TA] = 110.9p + 967.2(1−p) ms。均值优于 B 重算的 907 ms 只要 p > 7.0%;但只要有 1% 以上的请求走慢路径,p99 就是 967 ms。要满足 220 ms 的 p99,命中概率至少 99%。
排队阈值:何时改发空闲实例
DeepSeek V4.1 会话A 保留全局 KV 与编码器 SWA 状态,但要排队;B 立即可执行,要取回全局 KV(4.666 ms)并恢复 SWA 状态(假设 8 ms)。比的是预计完成时间,不是命中标志。
先想清楚优化谁
两任务负载压力实验:缓存优先时,目标请求约 1.38 s 完成,两任务同时结束;把目标请求移到空闲实例,它缩短到约 0.33 s,两任务却要到约 1.54 s 才全部完成。目标请求快了 1.05 s,全部任务晚了 0.16 s。
服务启动、扩缩容与故障恢复
新副本要先完成进程与 tokenizer 初始化、权重读取与分片、编译、KV 容量探测和 CUDA Graph 捕获,才能分担请求。首次试运行触发编译时,编译时间已包含在试运行里,总时间按最长依赖路径算(Breaking the Ice 对 vLLM 的分阶段分析)。
执行图值不值得准备
净收益 N·δ − Ts每执行一个 batch 省一次,所以收益按批执行次数算。
积压就绪后一起涌入
并发预取会改变谁先开始:某个 1024 token 请求单独运行时复用 1008 个 token;八个请求同时到达时,前四个各登记 1024 token 的预取,占满限额,后面的请求没登记上。最先完成的恰恰是没命中缓存、直接 prefill 的请求。缓存对象存在,请求也要先拿到预取空间才能用。
扩缩容还要考虑版本与硬件的对应:权重固定在不可改介质上时,加同型号卡可扩展同版本;部署新权重要配支持新版本的加速器,容量规划要为新旧版本并存预留资源。
启动结束时积压 λ·Ts Tdrain = λ·Ts / (μ − λ)
图 9-42 · 服务余量决定积压多快消退
连续流量模型。三条线的斜率就是服务率减到达率得到的净排空能力。效率降到假设值的九成,PD 的 D 池只剩约 4.10,就会错过第 60 秒的期限。
运行中重配置:先追平,再交接
计划内迁移可以利用源端还在跑:后台先复制不再变的上下文,源端继续生成;最后短暂停下,补齐迁移期间新增的状态,再交出执行权。最终交接点同时确定状态版本与执行权,防止漏掉源端最后的更新。
图 9-43 · 迁走一张 H20 上的 D worker
32 条请求 · 平均上下文 8704 · KV 41.1 GB源端每秒约 1166 次 decode 调用,每次追加 144 KiB,状态每秒只长约 0.172 GB;追赶速度是两条线斜率之差。复制速率降到增长率时两线平行,积压不再缩小。
Qwen3-8B 从 TP4 切到 TP8:剩下的全是软件准备
网络约 16.4 GB · 本地读写约 4.7 GB · 串行准备假设 9 s50 GbE 与 25 GB/s 网卡单看搬移相差四倍,加上 9 秒准备后总时间只差约 17%;走 NVLink(每张 A100 每方向 300 GB/s,发送最多的卡约 4.7 GB)也只能趋近 9 秒。这类差距靠更快的链路解决不了,要提前建通信组、预捕获执行图、把进程与调度解耦。切换 TP / SP×TP(ArcticInference 等)时预留两套权重和图能缩短等待,但会挤占 KV 空间;Elastic EP 扩组时,新卡要先拿到专家权重才能接任务。
部分故障与流式生成恢复
故障后源端数据可能读不出来,只能靠事先保存的状态和输出记录。先确定用户已经收到哪一段输出。三种目标:恢复足够状态继续 decode;按已确定的 token 重做 prefill;重新采样一段输出。前两种沿用户收到的序列继续;第三种重新做随机选择,后缀可能不同,对 RL rollout 来说改变了样本的生成过程。
图 9-44 · 输出记录定继续哪条序列,KV checkpoint 定从哪补算
输入 8192 · 已返回 1025 个输出token 级 WAL 在对外确认前可靠保存已确定的输出序列;KV 保存的是这段序列已经完成的计算。输出已返回,不表示对应 KV 已保存。DeepSeek V4 的生成服务采用这类机制,恢复时还要保持权重版本、位置索引和 decode 状态一致。故障范围由同步组决定:TP 或 EP 组丢一张卡可能停掉整个协作实例,其他完整副本还能继续服务。
部署方案的综合比较
P 产生的 KV 可以直接交给 D,也可以先进共享池再由 D 取回。内容可能相同,占用的链路和缓冲却不同。
图 9-45 / 9-46 · 直接交接 vs 经共享池中转
两条边都 25 GB/s、整份写完才能读时,中转多等约 48.3 ms。只有后续还有实例要用这份状态,才能用约 48.3 ms 的读取替代一次约 856 ms 的重算。视觉输入同理:EC 与语言 KV 标识不同,EC 命中减少 E 的工作,却不会自动省掉 P。
例 9.8 · 哪种部署能持续服务,并按期清空启动积压
章首资源与负载;服务从停止状态启动,三种方案都 10 秒后就绪;目标:持续处理新请求,并在开始启动后 60 秒内消除积压。两台服务器之间是共享的 25 GB/s 通道,前缀互不复用;共享池按整份写入后再读取,每请求在通道上搬两次。
五种方案一张表
完整副本持续低于到达率,先排除;理想分块捎带的共置 4.17 也要到第 63 秒才排空。两种 PD 稳态吞吐相同,但这批请求的前缀不会再被复用,中转让通道传输量翻倍、每请求多等 48.3 ms,64 GiB 共享池存下的 56 份前缀(MLA 为 119 份)一份也用不上。选四张 A100 做 P、四张 H20 做 D、P→D 直传。容量也够:H20 驻留 32 条请求的 KV 40.5 GiB + 1.125 GiB 接收缓冲 + 15.3 GiB 权重 ≈ 56.9 GiB < 89.4 GiB。
每千个合格请求的成本
Ceffective = 统计期总成本 / 满足质量与时限的请求数到达率仍是 3.5 时,4.55 的能力不会凭空多出请求,多出的部分用来消化突发和启动积压。提前退出的 Agent 少生成了 token、少占了资源,但没完成任务,不计入分母。成本与合格比例都是书中的教学假设。
负载一变,部署就要重算
前缀会被复用一次
多付的中转 48.3 ms + 后续取回 48.3 ms ≈ 96.6 ms,远低于 856 ms 重算,每次复用净省约 760 ms,共享池有了用处。代价是通道:每组请求写一次、读两次,共 3.375 GiB,3.5 组/s 要 12.7 GB/s,通道最多撑 6.9 组/s(MLA:1.61 GiB、6.0 GB/s、14.5 组/s)。
P 本地命中 6144
完整副本 4.90、原 PD 配比 4.55、两张 A100 做 P 其余六张做 D 5.69,排空分别约在第 35.1、43.2、26.0 秒。完整副本反而比原配比排空得早:原配比不再合适。
输出增到 4097
最佳分工也只有约 1.26 请求/s,怎么调配比都不够。复制三组八卡合计 3.78,刚够持续服务(24 张卡);还要按期排空需 ≥ 4.2,要四组 5.04(32 张卡)。额外资源的用途是加快积压消退。
单个阶段变快,配比也要跟着变
链路充足 · 每个 P 实例 20 请求/s,每个 D 实例 5 请求/sD 加速四倍后沿用 1:4,D 池涨到 80 而 P 还是 20;改成 1:1,两池都是 20,释放三个 D 实例。加速一个阶段的收益,体现为完成同样工作需要的资源变少了。
推导顺序:先把每个请求的工作量换算成各类资源需求;再按整数分配找出最忙的池或单元;按执行顺序计入状态传输与内存占用;最后用服务率减到达率,求积压持续多久。瓶颈是 D,加 P 不会减少积压;瓶颈是共享通道,加计算副本只会让更多请求排队等取回。
容易想错的地方
误区:PD 分离总能提高吞吐。
同构八张 A100 分离后反而从 3.05 降到 2.83:每请求 GPU 秒不变,整数划分还留下闲置。同构下分离换的是延迟稳定;吞吐收益来自异构硬件的强弱差异。
误区:AF 每步只传 576 KiB,比 PD 便宜。
单步确实更快,但 1024 步累计约 393 ms,是 GQA 一次 PD 交接的 8.1 倍、MLA 的 17 倍;输出越长差距越大。
误区:EP 越大,每个专家的 batch 越大。
平均行数 n·k/E 与卡数无关;EP 大了,每卡能互相抵消的专家变少,要等的卡却变多,最忙卡相对平均反而更忙。
误区:有缓存的机器就该接请求。
要比完成时间 max(Q,R)+C。A 排队 250 ms 时,B 经 200 GbE 取回 137 ms 就更快;预测命中率 90% 时均值好看,p99 仍是 967 ms。
误区:容量够大就能命中。
命中率很快饱和(容量不限也只有 51%);SSD 的真正约束是 1 DWPD 的写入寿命,只能接纳约 3.2% 的新 KV。
误区:换更快的链路就能缩短迁移。
TP4→TP8 迁移里 9 秒串行准备才是大头,NVLink 也只能逼近 9 秒;要靠提前建组、预捕获执行图。
计算和状态放在哪,决定能撑多大负载
一、先算工作,再分工
把请求换算成各阶段的 GPU 秒:A100 擅长 P、H20 擅长 D,四 P 四 D 让上限从 3.02 到 4.55。前缀命中把卡推向 D,输出变短把卡推向 P。
二、每次交接都要记账
PD 每请求交一次 KV,随上下文长度增长;AF 每层每步往返激活,怕启动开销;MoE 的 dispatch/combine 被最忙的卡和最挤的链路决定,副本要算显存和回本批数。
三、状态与时间线
共享 KV 用读取代替重算,但要保存得够久、读取能重叠、写入付得起;路由比完成时间;启动、迁移和故障恢复决定资源何时可用,服务余量决定积压多久消退。
同一套推导对不同上下文表示给出不同答案:交接状态从 GQA 换成紧凑 MLA,PD 交接时间减半,μPD 的链路项翻倍,AF 逐层交接不变,临界启动时间随之缩短。硬件变了,先固定请求与部署,找出新瓶颈,再重新分配各阶段资源。下一章转向训练。
动手验证
9-1 · 三种部署的调用次数与状态交接
对 8192 输入、1025 输出的请求,画出完整副本、PD 和共享 KV 三种部署,列出每请求调用数、KV 产生位置和跨实例交接;输出改为 1 个 token 时哪些工作不再需要;调用一次工具后继续生成,标出最后一个已返回、尚未生成 KV 的 token 位置(第 9.1 节 token 条)。
9-2 · 链路瓶颈与请求组成如何改变 PD 配比
复算例 9.2 的 25 种整数分配,把链路设为每秒恰好传一份 1.125 GiB(约 1.21 GB/s),求新上限;到达率恰等于上限时一次性加入十个请求,积压如何变化。再复核前缀命中与 129 输出两个情景;把效率改为 40%,判断 4P4D 是否仍高于 3.5(设计台的链路下拉框与效率滑块可直接试)。
9-3 · 专家 batch、指令集与权重位宽如何改变 CPU 瓶颈
求 AVX-512 与 AMX 下 CPU 从读取受限转为计算受限时的每专家 token 数,跨插槽 125 GB/s 时再算一次;比较 m = 1 与 128 的执行时间;权重改为每元素一字节、有效算力不变,交点往哪移。
9-4〔核心〕· PD 与 AF 的传输量、启动次数与通信重叠
25 GB/s,启动 1、5、20 μs 下比较一次 1.125 GiB 交接与总字节相同的 72 次交接;按例 9.4 的 AF 载荷算 8192 输入、1025 输出整条请求的累计交接时间。四个 micro-batch 注意力 2 ms、FFN 3 ms,比较串行与理想流水,求额外开销的上限。
9-5 · 异构推理的权重容量与 CPU 处理能力约束
从 DeepSeek V4-Flash 或 Kimi K2 的配置还原权重存放、GPU 缓冲与主存需求;增加并发后预测被访问专家数、各专家任务数与最重的 NUMA 节点;构造总权重装得下、但到达率超过 CPU 计算能力的条件,推导积压增长率。
9-6 · 专家副本的容量约束与复制成本回收
八个专家收到 [32,16,8,4,2,1,1,0] 行,比较只算有效行、非空专家补到 32、全部补到 32 的计算量;按例 9.6 求最少回本批数;接收卡只有 32 MiB 时为什么先排除;热点随时间变化时如何用观察窗口预测累计收益。
9-7〔核心〕· KV 保存、取回与重算的收益条件
1.125 GiB 前缀后续共用 100 次,比较重算一次后驻留、取回一次后驻留、每次远程读三种方式;计入写入与保留时间推导保存何时更合算;解释共享 CPU 池从 4 GiB 增到 8 GiB 保住了哪些复用。再按 DGX A100 每卡配置:间隔 5 分钟需多大容量、用到哪几级;新输入 128 与 512 token 时逐层预加载的总时间与需提前读入的层数;1 DWPD 下 SSD 能长期接纳的新 KV 比例,命中率 50% 时变为多少。
9-8 · KV 缺页与版本不兼容时的恢复选择
解释读了 1024 token、只复用 1008 token 时两种计量方式的差异;对缺页、截断页、版本不兼容分别给出继续等待、部分重算与放弃缓存的判断条件,并说明如何检查请求能否完成、数据是否修复、输出是否与不用缓存时一致。
9-9 · 缓存路由的带宽交点与首 token 尾延迟
推导例 9.7 中 B 远端取回分别与 A 本地命中、B 本地重算打平时的带宽;求 p = 0.5、0.9、0.99 时选 A 的首 token 均值与 p99;HBM 副本不可用但 CPU 副本可用、取回能与 80 ms 排队重叠时,两点分布模型还适用吗。
9-10〔核心〕· 长短输出混合负载下的 PD 扩容与排队
3.5 请求/s 中一半输出 1025、一半输出 4097,均为 8192 输入、无命中。求两类卡在两种输出下的 D GPU 秒与平均需求,枚举八卡的所有 P/D 组合;允许复制八卡组合,分别求持续服务与“10 秒启动、60 秒内清空积压”所需的最少组数;把长输出请求集中在每分钟前十秒到达,画出队列变化。
9-11 · MLA 与 GQA 的 PD / AF 判断
把交接状态换成 DeepSeek-V3 紧凑 MLA(61 层、dc=512、dr=64、BF16),保持例 9.2 的阶段能力与例 9.4 的 AF 载荷、5 μs 启动:求 8192 token 的状态字节数与 25、50 GB/s 下的交接时间;μPD 的链路项与链路成为约束的带宽;两种链路的 α*;输出 1025 与 4097 时 AF 累计交接是 PD 的多少倍;计入每步 2.05 GFLOPs 查询变换后四张 H20 是否够用。
解题示范 · CPU 专家执行在多大 batch 下由读取受限转为计算受限
读取项等于计算项:2mPe/CC = 2Pe/BD,得 m = CC/BD(BF16 每参数 2 字节、每行每参数 2 次浮点运算,两个系数约掉)。AVX-512:1.8 TFLOP/s ÷ 220 GB/s ≈ 8.2;AMX:21.3 ÷ 220 ≈ 97;跨插槽 125 GB/s 时分别约 14 与 170,单行读取时间增加约 76%。这个等时点与图 9-14 的 71/72、688/689 回答的是不同问题:前者是 CPU 自身从带宽受限转为计算受限的分界,后者比较的是包含权重搬移的完整 CPU、GPU 两条路径。