对应 Maps to:原课没有对应的一次课。CS349D 默认学生熟悉分布式系统和 GPU 集群;第 6–9 讲(并行、prefill / decode 解耦、MoE、上下文管理)都建立在”多卡之间通信要多久”的账上。这篇前置讲为没有这类背景的读者补上这本账。 依据说明:硬件规格来自 NVIDIA 的公开资料(DGX H100 用户指南、NVLink / NVSwitch 的规格;GB200 NVL72 的数字来自公开资料的汇总)。集合通信算法依据 R. Thakur, R. Rabenseifner, W. Gropp, Optimization of Collective Communication Operations in MPICH(IJHPCA 2005)和 P. Patarasuk, X. Yuan, Bandwidth Optimal All-reduce Algorithms for Clusters of Workstations(JPDC 2009);NCCL 的算法、协议与传输方式依据 Z. Hu 等的 Demystifying NCCL: An In-depth Analysis of GPU Communication Protocols and Algorithms(2025)。并行方式依据 Megatron-LM(Shoeybi 等,2019)、Megatron 的序列并行(Korthikanti 等,2022)、GPipe(Huang 等,2019)、Ring Attention(Liu 等,2023)。 配套代码 Code:
code/prereq5/(numpy;5 个脚本 + 1 个共享模块;全部 1 秒左右跑完) 预计阅读时间:3 小时(含运行代码)
0. 本讲导航 · How to read this lecture
0.1 学习目标 Learning goals
学完这一篇,你应该能够:
- 说出推理为什么要用多块 GPU,以及代价是什么。
- 画出 GPU 集群的互连层次(HBM、NVLink / NVSwitch、PCIe、网卡与 InfiniBand / RoCE、存储),说出各层带宽和延迟的数量级;解释 RDMA 和 GPUDirect RDMA 省掉了什么。
- 用 α–β 模型估计一次传输的时间,判断它受限于延迟还是带宽。
- 说出 broadcast、reduce、all-reduce、reduce-scatter、all-gather、all-to-all 各做什么,以及 all-reduce = reduce-scatter + all-gather。
- 比较 ring、递归加倍、Rabenseifner、树、交换机内归约这几种 all-reduce 算法的代价,解释为什么要按消息大小和拓扑选算法、为什么要分层。
- 说出数据并行、张量并行(以及序列并行)、流水线并行、专家并行、上下文并行各要通信什么,它们适合放在哪一层互连上。
- 用切块流水、逐层传输、两批交错把通信藏在计算后面,并说出它的条件和极限。
0.2 先修与本讲范围 Prerequisites & scope
| 默认你已经会 Assumed | 本讲不展开 Out of scope |
|---|---|
| 第 1 讲:权重与 KV 的显存账、decode 受限于带宽 | 网络协议栈(TCP、拥塞控制)、交换机的内部结构 |
| 前置讲 P1(roofline、HBM)、P2(参数量、KV、显存预算) | 并行策略的搜索与具体系统(第 6 讲 FlexFlow、Pope 等) |
| 前置讲 P4(建议):Little 定律、扇出与尾延迟 | 训练里的通信(梯度同步、ZeRO)只点到 |
0.3 本讲地图 Map
§1 为什么要多卡,代价是什么
§2 互连:HBM、NVLink / NVSwitch、PCIe、InfiniBand / RoCE、RDMA 与 GPUDirect、存储 ← 代码 01
§3 α–β 模型:延迟受限还是带宽受限 ← 代码 01
§4 集合通信:六种操作、它们的关系、每个设备至少要传多少;MoE 的 all-to-all ← 代码 02
§5 all-reduce 的算法:ring、递归加倍、Rabenseifner、树、交换机内归约;分层;NCCL ← 代码 03
§6 并行方式的通信模式:数据 / 张量(序列)/ 流水线 / 专家 / 上下文并行 ← 代码 04
§7 计算与通信的重叠:切块、逐层传输、两批交错 ← 代码 05
§8 与推理系统的联系(只想快速浏览的读者读这一节)
§9–13 小结、常见误区、练习、延伸阅读、下一步
0.4 记号 Notation
| 符号 | 含义 |
|---|---|
| 参与通信的设备(GPU)数 | |
| 每个设备上要参与集合通信的数据量(字节) | |
| 每条消息(每一步)的启动延迟:软件开销、同步、链路和交换机的延迟 | |
| 每个设备每个方向的有效带宽(字节 / 秒) | |
| TP / PP / DP / EP / CP / SP | 张量 / 流水线 / 数据 / 专家 / 上下文 / 序列并行 |
本篇的带宽都是每个 GPU、每个方向的有效带宽(标称值 × 80%,和第 6 讲相同)。厂商常报”双向合计”,例如 H100 的 NVLink”900 GB/s”是两个方向加起来,每个方向 450 GB/s。
0.5 关于数字 · About the numbers
本篇的时间来自 α–β 模型:有效带宽 = 标称 × 80%,α 是数量级的假设值(NVLink 2 µs、PCIe / InfiniBand 5 µs 等)。代码 02 用逐条消息的记账核对了每种算法的字节数和公式。数字说明量级和交叉点的位置,不是某台机器、某个 NCCL 版本的实测;真实的小消息延迟往往比这里低(NCCL 的低延迟协议、推理引擎的自定义内核)。
1. 为什么要多卡 · Why multiple GPUs
一块 H100 有 80 GB 显存、3.35 TB/s 带宽、989 TFLOP/s 算力。推理在三件事上会撞到它的天花板(前置讲 P2 §6):
- 放不下:Llama-3-70B 的 BF16 权重 141 GB,一块卡放不下;即使放得下,剩下的显存也装不了多少 KV。DeepSeek-V3 的 FP8 权重 671 GB,要 8 块 141 GB 的 H200。
- 不够快:batch 1 的 decode 每步要把权重读一遍,时间 = 字节 ÷ 带宽。把权重切到 8 块卡上,每块只读 1/8,8 块卡的带宽加起来让每个 token 快近 8 倍(前置讲 P2 §6.2:70B 的 TPOT 下界从单卡放不下变成 8 卡约 5 ms)。
- 不够多:一个副本能同时服务的请求有限,多放几个副本,吞吐就翻几倍。
代价是通信:模型一旦切开,每一层都可能要在卡之间交换数据;而卡与卡之间的链路比卡内的 HBM 慢一个数量级以上。多卡推理的全部学问,就是”怎么切,才能让通信少、通信快、通信藏得住”。
2. 互连 · Interconnects
2.1 一张层次图
GPU 内部 HBM:3.35 TB/s(H100) ← 最快
│
节点内(8 块卡) NVLink 4 经 NVSwitch:每块卡每方向 450 GB/s(双向 900 GB/s)
│ PCIe Gen5 x16:每方向约 64 GB/s(CPU 内存、网卡、SSD 都挂在 PCIe 上)
│
节点之间 网卡:InfiniBand NDR 或 RoCE,每张 400 Gb/s = 50 GB/s;通常每块 GPU 配一张
│ 以太网:25–400 Gb/s
│
存储 NVMe SSD:每块几 GB/s;远端存储更慢 ← 最慢
代码 01 演示 1 列出 9 种链路的有效带宽(标称 × 80%)和假设的 α:
| 链路 | 带宽(每方向) | α | 半带宽消息 | 传 1 MB | 传 1 GB |
|---|---|---|---|---|---|
| NVLink 5(B200 / GB200) | 720 GB/s | 2 µs | 1.44 MB | 3.39 µs | 1.39 ms |
| NVLink 4(H100) | 360 GB/s | 2 µs | 720 KB | 4.78 µs | 2.78 ms |
| PCIe Gen5 x16 | 51 GB/s | 5 µs | 256 KB | 24.53 µs | 19.54 ms |
| InfiniBand NDR 400 Gb/s | 40 GB/s | 5 µs | 200 KB | 30.00 µs | 25.01 ms |
| 以太网 100 Gb/s | 10 GB/s | 15 µs | 150 KB | 115.00 µs | 100.02 ms |
| NVMe SSD(一块) | 5.6 GB/s | 50 µs | 280 KB | 228.57 µs | 178.62 ms |
| 以太网 25 Gb/s | 2.5 GB/s | 20 µs | 50 KB | 420.00 µs | 400.02 ms |
节点内的 NVLink 比跨节点的网卡快近一个数量级,比普通以太网快两个多数量级;而最快的 NVLink 也比 HBM 慢近 10 倍——在卡与卡之间搬数据,永远比在一块卡里读数据贵。
2.2 节点内:NVLink 与 NVSwitch
NVLink 是 NVIDIA GPU 之间的专用高速链路。H100 有 18 条 NVLink 4,合计每方向 450 GB/s;B200 的 NVLink 5 翻倍到每块卡双向 1.8 TB/s。NVSwitch 是 NVLink 的交换芯片:DGX H100 里 8 块 GPU 都连到 NVSwitch 上,任意两块卡之间都能以全速通信(全互连),而不是只能和相邻的卡说话。H100 这一代的 NVSwitch 还能在交换机里直接做加法(NVLink SHARP,§5.4)。
NVLink 能直接连通的范围叫一个 NVLink 域。DGX H100 是 8 块卡;GB200 NVL72 用 NVSwitch 把一整个机柜的 72 块 GPU 连成一个 NVLink 域,合计约 130 TB/s。这改变了并行的设计空间:以前张量并行、专家并行只能限制在 8 块卡里,现在可以在 72 块卡上全走 NVLink(第 7 讲 Dynamo 和第 8 讲 Helix 的很多结果都建立在它上面)。
2.3 节点之间:网卡、InfiniBand 与 RoCE
跨节点要经过网卡。GPU 服务器通常给每块 GPU 配一张就近的网卡:DGX H100 有 8 张 400 Gb/s 的 ConnectX-7(另有几张给存储和管理用)。主流的两种网络:
- InfiniBand:为高性能计算设计的网络,原生支持 RDMA,延迟低,交换机还能做集合通信的归约(SHARP)。NDR 一个端口 400 Gb/s。
- RoCE(RDMA over Converged Ethernet):在以太网上跑 RDMA,成本和生态上更接近普通数据中心网络。
代码 01 演示 5 算了这个落差:一个 DGX H100 节点内部 8 块卡的 NVLink 合计每方向 3.6 TB/s,对外 8 张网卡合计每方向 400 GB/s——节点内是节点间的 9 倍。所以”每一层都要通信”的切法(张量并行、专家并行)尽量放在 NVLink 域内;跨节点只放通信少的(流水线并行、数据并行、解耦部署的 KV 传输)。
2.4 RDMA 与 GPUDirect
普通的网络通信要经过操作系统内核:数据从应用的缓冲区拷到内核、再交给网卡,接收方再反过来拷一遍,每一步都要 CPU 参与。RDMA(remote direct memory access)让网卡不经过内核、直接读写远端机器的内存:零拷贝、几乎不占 CPU、延迟低。
GPUDirect RDMA 再进一步:网卡直接读写 GPU 显存,数据不再经过 CPU 内存中转。代码 01 演示 4(跨节点传 1 GB):经主机中转、不流水时要 64 ms(GPU → CPU 内存 → 网络 → CPU 内存 → GPU,三段依次),分块流水也要 25 ms 且占用 CPU 内存带宽;GPUDirect RDMA 只有网络本身的 25 ms。NCCL 只在 GPU 和网卡挂在同一个 PCIe 交换机下时才用它——这也是为什么每块 GPU 要配一张”就近”的网卡。
还有 GPUDirect Storage:NVMe SSD 直接读写 GPU 显存,用于从存储加载权重或 KV。Mooncake 的传输引擎(第 9 讲)、DeepSeek 的 DeepEP(第 16 讲)都建立在 RDMA 之上。
2.5 推理里的具体传输
代码 01 演示 3(Llama-3-70B,BF16):
| 传输 | 大小 | NVLink 4 | IB NDR |
|---|---|---|---|
| 张量并行 decode:一层的激活(批 1) | 16 KB | 2.05 µs | 5.41 µs |
| 张量并行 decode:一层的激活(批 64) | 1 MB | 4.91 µs | 31.21 µs |
| 张量并行 prefill:一层的激活(4,096 token) | 67 MB | 188 µs | 1.68 ms |
| 解耦部署:4,096 token 提示的全部 KV | 1.34 GB | 3.73 ms | 33.56 ms |
| 冷启动:全部权重 | 141 GB | 392 ms | 3.53 s |
- decode 时张量并行每层传的激活只有十几 KB 到 1 MB:时间几乎全是 α,而一步 decode 有 80 层、每层 2 次集合通信。
- 解耦部署要把 prefill 算出的 KV 搬到 decode 的机器:4K 的提示有 1.34 GB,经一张网卡要 30 多毫秒(8 块卡 prefill 这个提示约 105 ms)。8 张网卡并行只要 4 ms,再逐层边算边传(§7.3),就几乎藏住了(第 7、9 讲)。
- 冷启动:从一块 NVMe SSD 读 141 GB 的权重要 25 秒,已经在 CPU 内存里时经 8 条 PCIe 只要 0.34 秒——第 12 讲多模型服务的冷启动就是这笔账。
3. α–β 模型 · The α–β model
传一条 字节的消息:
是不管消息多大都要付的固定开销, 是真正传数据的时间。两项相等时, 叫半带宽消息大小:消息比它小时,连一半的带宽都用不上。代码 01 演示 2:
| 链路 \ 消息 | 16 KB | 256 KB | 1 MB | 16 MB |
|---|---|---|---|---|
| NVLink 4 | 2% | 26% | 58% | 96% |
| InfiniBand NDR | 7% | 56% | 83% | 99% |
| 以太网 25 Gb/s | 24% | 84% | 95% | 100% |
(表里是有效带宽占峰值的比例。)同样传 256 KB,NVLink 只用到四分之一的带宽,以太网反而用到 84%——不是以太网好,而是它本来就慢。链路越快,要用满它需要的消息越大。NVLink 4 的 是 720 KB,而 decode 时张量并行每层传的激活往往比它小得多。
这个模型给出两条贯穿全篇的经验:
- 消息小时优化 α:减少步数、减少消息条数、把小消息合并成大消息(§5 的算法选择、推理引擎的自定义 all-reduce 内核)。
- 消息大时优化 β:减少每个设备要传的字节(带宽最优的算法、分层通信、交换机内归约)、让通信和计算重叠(§7)。
4. 集合通信 · Collective communication
4.1 六种操作
集合通信(collective)是一组设备一起参与的通信操作。代码 02 演示 1 用 4 个设备、每个设备一个长度 4 的数组展示:
| 操作 | 做什么 | 例子(输入 GPU i 有 [10i, 10i+1, 10i+2, 10i+3]) |
|---|---|---|
| broadcast | 一个设备的数据发给所有人 | 每人都得到 GPU0 的 [0, 1, 2, 3] |
| reduce | 求和,结果只在一个设备上 | GPU0 得到 [60, 64, 68, 72] |
| all-reduce | 求和,每个人都拿到 | 每人都得到 [60, 64, 68, 72] |
| reduce-scatter | 求和,结果切成 块、每人拿一块 | GPU0 拿到第 1 块 [64],GPU1 拿到 [68]…… |
| all-gather | 每人一块,拼成完整的给每个人 | 每人都得到 [0, 10, 20, 30] |
| all-to-all | GPU i 的第 j 份发给 GPU j | GPU j 得到 [j, 10+j, 20+j, 30+j]:一次”矩阵转置” |
外加最基本的点对点(send / recv):一个设备发、另一个收。
它们之间有一个很重要的关系:all-reduce = reduce-scatter + all-gather。先把和切开、每人负责一块(reduce-scatter),再把各块拼回来发给所有人(all-gather)。这个拆法有两个用处:ring all-reduce 就是这样实现的(§5.1);序列并行可以在两步之间插入别的计算(§6.2)。
推理里最常用的是:all-reduce(张量并行,每层两次)、all-gather 与 reduce-scatter(序列并行、DP 注意力)、all-to-all(专家并行)、点对点(流水线并行、解耦部署的 KV 传输)。
4.2 每个设备至少要传多少
all-reduce 的结果依赖所有设备的数据。可以证明,每个设备至少要发送 字节(reduce-scatter 和 all-gather 各 )。代码 02 演示 2(8 个设备,每个 8 MB,NVLink 4):
| 算法 | 步数 | 每个设备发送 | ÷ 下界 | 时间 |
|---|---|---|---|---|
| 朴素(每人发给所有人) | 1 | 56 MB | 4.00 | 157.56 µs |
| ring | 14 | 14 MB | 1.00 | 66.89 µs |
| 递归加倍 | 3 | 24 MB | 1.71 | 72.67 µs |
| Rabenseifner | 6 | 14 MB | 1.00 | 50.89 µs |
| 二叉树(reduce + broadcast) | 6 | 24 MB | 1.71 | 145.33 µs |
五种算法的结果完全一样,差别全在”怎么传”:步数(决定付几次 )和每个设备传的字节(决定 那一项)。ring 和 Rabenseifner 恰好达到下界,叫带宽最优;而且这个量 几乎不随设备数增长——加卡不会让每块卡多传。
4.3 all-to-all 与 MoE
专家并行(第 8 讲)里,每块卡放一部分专家;每个 token 要被发到它选中的专家所在的卡上(dispatch),算完再发回来(combine)——两次 all-to-all。all-to-all 的麻烦在于负载不均:一个热门专家所在的卡要收的数据比别人多,而所有卡都要等它收完才能开始算。代码 02 演示 3(8 块卡、每块一个专家、top-2):均匀路由时 dispatch 约 181 µs;一个专家热 4 倍时,它所在的卡要收的数据是平均的约 2.5 倍,dispatch 变成 415 µs(2.3 倍)。这是前置讲 P4 §4.3”扇出”在通信上的样子;第 8 讲的冗余专家和负载均衡都是为了压低这个”最忙的卡”。
5. all-reduce 的算法 · All-reduce algorithms
5.1 ring:带宽最优,步数线性
设备排成一个环,数组切成 块:
- reduce-scatter: 步。每一步,每个设备把手上一块的”部分和”发给下一个设备,对方加到自己的同一块上。结束时每块都在某个设备上加齐了 份。
- all-gather:再 步,把加齐的块沿环转发,直到每个设备都有全部 块。
每步每个设备只发 字节、所有链路同时在忙,总时间:
字节是最优的,但要走 步:8 块卡 14 步,64 块卡 126 步。(第 6 讲 §1.3 的代码逐步打印了它的每一步。)
5.2 递归加倍与 Rabenseifner:步数对数
- 递归加倍(recursive doubling):第 步,每个设备和”编号只在第 位不同”的设备交换整个数组再相加。 步就完成,延迟最优;但每步都传整个数组,共 ,带宽很差:
- Rabenseifner(递归减半 + 递归加倍):reduce-scatter 阶段每步和一个伙伴交换一半(第一步和距离 的设备交换各自”对方负责的那一半”,下一步在剩下的一半里和距离 的设备交换……);all-gather 阶段倒过来。 步,字节和 ring 一样最优:
两头都好,代价是要求设备数是 2 的幂、通信对象每步都在变。
- 树:先沿一棵二叉树把数据归约到根,再沿树广播下去。朴素的树每步都传整个数组,根附近的设备最忙;NCCL 用的是双二叉树:两棵互补的树(一个设备在一棵树里是内部节点,在另一棵里就是叶子),数据切成两半各走一棵,再分块流水——既有对数级的步数,又能接近满带宽。
5.3 消息大小决定算法
代码 03 演示 1(8 块卡,NVLink 4):
| 算法 \ 消息 | 4 KB | 1 MB | 16 MB | 1 GB |
|---|---|---|---|---|
| ring | 28.0 µs | 32.9 µs | 105.8 µs | 4.9 ms |
| 递归加倍 | 6.0 µs | 14.3 µs | 139.3 µs | 8.3 ms |
| Rabenseifner | 12.0 µs | 16.9 µs | 89.8 µs | 4.9 ms |
| 二叉树(不流水) | 12.1 µs | 28.7 µs | 278.7 µs | 16.7 ms |
| 交换机内归约 | 4.0 µs | 6.8 µs | 48.4 µs | 2.8 ms |
小消息时只看 α 的次数,递归加倍最快;大消息时只看字节,ring 和 Rabenseifner 最快。代码 03 演示 2 把设备数增加到 64 块、全部走 InfiniBand:ring 要走 126 步,1 MB 的 all-reduce 光 α 就要 630 µs,递归加倍只要 180 µs;交叉点向更大的消息移动。没有”最好的算法”,通信库要按消息大小、设备数、拓扑选择。
5.4 交换机内归约
如果交换机自己会做加法,每块卡只需要把数据发给交换机一次、再从交换机收一次结果:
传输量约是 ring 的一半,步数也最少。InfiniBand 交换机的 SHARP 和 H100 这一代 NVSwitch 的 NVLink SHARP(NCCL 里的 NVLS 算法)都提供这种能力。上表里它在各种大小下都最快(这是理想值;真实的收益要扣掉实现开销)。
5.5 分层 all-reduce
跨节点时,一个”所有卡排成一个环”的扁平 ring,每一步都要等最慢的那条链路(网卡),节点内的 NVLink 完全没被利用。分层的做法:
- 每个节点内用 NVLink 做 reduce-scatter:每块卡只剩 ( 是每节点的卡数);
- 各节点里本地编号相同的卡之间,对各自那 做跨节点的 all-reduce—— 张网卡同时在用;
- 每个节点内 all-gather。
代码 03 演示 3(4 个节点 × 8 块卡):分层在 64 KB 到 1 GB 的各种大小下都比扁平的环快约 5 倍(1 GB:9.61 ms vs 48.75 ms)。NCCL 会根据拓扑自动这样组织。
5.6 NCCL
NCCL(NVIDIA Collective Communications Library)是 GPU 上集合通信的事实标准,PyTorch、vLLM、SGLang 都用它。它做几件事:
- 拓扑感知:探测 NVLink、PCIe、网卡的连接方式,建立环和树(分层的)。
- 算法:Ring、Tree(双二叉树)、CollNet(用网络交换机的 SHARP)、NVLS(用 NVSwitch 的 NVLink SHARP)等。
- 协议:同一个算法,数据怎样从一块卡交到下一块卡,有三种协议。“Demystifying NCCL” 报告的量级:
| 协议 | 同步方式 | 带宽 | 每跳延迟 |
|---|---|---|---|
| Simple | 大块数据 + 内存屏障 | 接近峰值 | 约 6 µs |
| LL(low latency) | 每 4 字节数据配 4 字节标志,接收方轮询标志 | 峰值的 25%–50% | 约 1 µs |
| LL128 | 每 128 字节里 8 字节做标志 | 约 95% | 约 2 µs |
代码 03 演示 4 用这些量级算 8 块卡的 ring all-reduce:64 KB 以下 LL 最快、16 MB 时 LL128 最快、256 MB 以上 Simple 最快——和算法的选择是同一个道理。
- 自动选择:NCCL 对每种”算法 + 协议”用代价模型估计时间,每次调用选最快的。
- 传输方式:节点内走 NVLink 的点对点(或者 PCIe、共享内存),节点间走 InfiniBand / RoCE 的 RDMA(能用时用 GPUDirect RDMA),都不行时退回 TCP 套接字。
5.7 推理里的小消息
代码 03 演示 5:Llama-3-70B 用张量并行 TP8(NVLink 4),decode 一步要做 80 层 × 2 = 160 次 all-reduce,每次 字节:
| 批 B | 每次大小 | ring | 递归加倍 | 交换机内归约 | 读显存的时间 |
|---|---|---|---|---|---|
| 1 | 16 KB | 4.49 ms | 0.98 ms | 0.65 ms | 6.61 ms |
| 64 | 1 MB | 5.30 ms | 2.36 ms | 1.11 ms | 8.58 ms |
| 256 | 4 MB | 7.74 ms | 6.55 ms | 2.50 ms | 14.59 ms |
用通用的 ring,160 次小通信一步就要 4.5 ms,是读显存时间的三分之二。(这里每步 = 2 µs、ring 走 14 步,对小消息是偏悲观的估计。)所以推理引擎为小消息写了专门的 all-reduce 内核:vLLM 的 custom all-reduce 在 NVLink 全互连、消息小于 8 MiB 时直接读写其他卡的显存,一两步完成;或者用 NCCL 的 LL 协议、NVLS。这也是第 6 讲 §2.3”张量并行的通信不随卡数减少、TP 太宽反而变慢”的一个原因。
6. 并行方式的通信模式 · Communication patterns of parallelism
6.1 数据并行(副本)
推理里的数据并行就是多放几个完整的副本,各自服务不同的请求,彼此不通信(训练时要同步梯度,推理不用)。代价是每个副本都要放下全部权重。它是吞吐的最简单扩展方式,多个副本之间靠路由器分配请求(第 11 讲)。
6.2 张量并行与序列并行
张量并行把每一层的矩阵切到 块卡上。Megatron-LM 的切法:MLP 的第一个矩阵(SwiGLU 的 gate 和 up)按列切,每块卡负责 个中间神经元;第二个矩阵(down)按行切。SiLU 和逐元素乘法只作用在每块卡自己的那几列上,所以两个矩阵乘法之间不用通信;最后一次 all-reduce 把各卡的部分和加起来。注意力同理:按头切 Q、K、V(每块卡负责几个头),输出投影按行切,一次 all-reduce。所以每层两次 all-reduce。
代码 04 演示 1 验证了这个切法和单卡结果一致,并比较了一个”错误”的切法:如果第一个矩阵按行切,SiLU 之前就必须先 all-reduce 出完整的 中间结果——两次、每次是输出的 3.5 倍大,每块卡要多传 7 倍的字节。切法的设计就是在”哪里非线性、哪里必须通信”之间找缝隙。
序列并行(Megatron-SP,Korthikanti 等 2022):张量并行下,MLP 和注意力之外的 RMSNorm、残差在每块卡上都是完整的一份(重复计算、重复存储)。序列并行把这部分按 token 切开,每块卡只处理 个 token;进入 MLP 前 all-gather 拼出完整的输入,出 MLP 时用 reduce-scatter 代替 all-reduce,直接得到自己那 个 token 的输出。演示 1 里它的通信量和张量并行完全一样(all-reduce = reduce-scatter + all-gather),但激活的显存和逐元素计算都分摊到了 块卡上。第 16 讲 SGLang 的 DP 注意力用的也是这对组合。
张量并行每层都要通信、而且是”小而多”的通信,所以几乎总是放在一个 NVLink 域内:代码 04 演示 3,TP8 decode 一步在 NVLink 上通信约 2–5 ms,走 InfiniBand 要 15–19 ms,比读一遍权重(约 6.6 ms)还慢好几倍。
6.3 流水线并行
流水线并行把模型按层切成 段,每段放在一块卡上,激活从一段传到下一段(点对点)。通信量很小:一步 decode 每个微批只在 7 个段边界各传一次激活(批 64 时每次 1 MB),跨节点也不怕。
它的问题在别处。代码 04 演示 4(4 段,每段 2 ms):一个微批生成下一个 token,必须先让上一个 token 走完 4 段(自回归的依赖),所以只有一个微批时每块卡只有 1/4 的时间在干活;要有至少 4 个微批同时在流水线里,利用率才到 98%。而且每个 token 的间隔始终是 4 × 2 ms ≈ 8.15 ms,不比单卡更短:流水线并行提高吞吐,不降低延迟。训练时的”流水线气泡”(第一个微批进入前、最后一个微批离开后,有的段在空等)在推理里表现为”同时在跑的微批不够多”。第 6 讲 §2.5 有更完整的讨论。
6.4 专家并行
专家并行把 MoE 层的专家分到不同的卡上,每层两次 all-to-all(§4.3)。decode 时每个 token 只去 top-k 个专家、token 又少,代码 04 演示 3 里 Mixtral-8x7B 用 EP8 时 decode 一步每块卡只发约 7 MB,但每层要和 7 块卡各交换一次,时间主要花在 α 上;prefill 或大批时字节就大了。再加上负载不均,大规模专家并行跨节点时通信是主要矛盾,要靠专门的通信库(DeepEP 用 RDMA 和 NVLink 直接在 GPU 上发起通信)和计算—通信重叠(§7.4、第 8、16 讲)。
6.5 上下文并行与 ring attention
长上下文时,一段序列的 KV 一块卡放不下,或者 prefill 太慢。上下文并行把序列按 token 切到 块卡上。ring attention(Liu 等 2023):每块卡拿着自己那段的 Q;K、V 的块沿环传一圈,每一步用自己的 Q 和”这一步手上的 KV 块”算部分注意力,用在线 softmax(第 4 讲 §3.2 的 和 )把各块的结果合并。代码 04 演示 2 验证它和单卡完全一致(误差 )。
关键在于:每一步的注意力计算随块长 平方增长,要传的 KV 块只线性增长。对 Llama-3-70B 的一层(64 个 query 头、8 个 KV 头),每块卡的 token 数超过约 240(NVLink)/ 2,163(InfiniBand)时,传 KV 就能完全藏在计算后面。所以长上下文的 prefill 很适合这样切(第 6 讲 §5.2 的 LoongServe)。带因果掩码时,各卡的工作量不均,实际系统用”之字形”的切法来平衡。
6.6 一张对照表
| 并行方式 | 切什么 | 通信 | 每层 / 每步 | 适合的链路 | 主要收益 |
|---|---|---|---|---|---|
| 数据并行(副本) | 请求 | 无 | — | 任意 | 吞吐 |
| 张量并行 | 每层的矩阵(按头 / 按列行) | all-reduce | 每层 2 次 | NVLink 域内 | 延迟(分摊读权重)、放得下 |
| 序列并行 | MLP 外的 token | reduce-scatter + all-gather | 每层 2 对 | NVLink 域内 | 激活显存 |
| 流水线并行 | 层 | 点对点 | 每个段边界 1 次 | 可以跨节点 | 放得下、吞吐 |
| 专家并行 | 专家 | all-to-all | 每 MoE 层 2 次 | NVLink 或 RDMA | 放得下、专家的批更大 |
| 上下文并行 | token(KV) | 点对点(环) | 每层 步 | 视块长而定 | 长上下文 |
真实部署常常是组合:例如节点内 TP8、节点间 PP2;或者注意力用数据并行、MoE 用专家并行(DeepSeek-V3 的部署,第 8 讲)。通信多的放在快链路上,通信少的才能跨慢链路——这是第 6 讲 Alpa 的核心观察,也是 FlexFlow 一类自动搜索要处理的问题。
7. 计算与通信的重叠 · Overlapping computation and communication
7.1 切块流水
通信和计算用的是不同的硬件(网卡 / NVLink 的拷贝引擎 vs SM),可以同时进行。把一份工作切成 块,第 块算完就开始传,同时开始算第 块:
代码 05 演示 1(计算 1 ms,每块通信多付 10 µs 的 α):通信 1 ms 时,不重叠 2.01 ms,切成 8 块 1.20 ms,切成 256 块反而 3.56 ms——每块都要多付一次 α,切得太细反而更慢。通信比计算长时(2 ms),再怎么重叠也省不掉通信本身,这时要减少通信量。
7.2 张量并行的 prefill
代码 05 演示 2:Llama-3-70B、TP8、prefill 4,096 个 token。每层每块卡计算约 1.32 ms,两次 64 MB 的 all-reduce 约 0.71 ms(ring,NVLink 4),约占每层时间的三分之一。按 token 切成 4 块、一块的 all-reduce 和下一块的矩阵乘法同时进行,80 层一共省下约 38 ms 的 TTFT;切成 16 块又因为 α 变慢。重叠的前提是”下一块的计算不依赖这一块的通信结果”——按 token 切块正好满足。
7.3 逐层传输 KV
代码 05 演示 3:解耦部署时,prefill 的 KV 要传给 decode 的机器。算完再传,传输直接加在 TTFT 上:4K 的提示用 1 张网卡多出 33.6 ms、8 张网卡多出 4.2 ms。逐层传输:每算完一层就把这一层的 KV 传走,和下一层的计算同时进行,prefill 结束时只剩最后一层的 KV 露在外面——8 张网卡时只多出 57 µs。32K 的长提示也一样:每层的计算(约 13 ms)仍然比传输长。DistServe、Mooncake(第 7、9 讲)都按层传输 KV。
7.4 两批交错
MoE 的一层里,all-to-all 和专家计算是串行的:dispatch → 算专家 → combine。两批交错(two-batch overlap,TBO):把一批请求分成两半,一半在做 all-to-all 时另一半在计算。代码 05 演示 4(计算 c = 1):通信和计算差不多大时(a = 1)收益最大,1.33 倍;通信很小时没什么可藏,通信远大于计算时最多只能把计算藏进去。SGLang 的 TBO(第 16 讲)、MegaScale-Infer 的 ping-pong 流水线(第 8 讲)都是这个思路。
重叠不是免费的:通信内核也要占用一些 SM 和显存带宽,计算会被拖慢一点;切块、分批还要额外的显存和调度复杂度。实践中要用性能分析工具(如 Nsight Systems)确认通信是不是真的被藏住了。
8. 与推理系统的联系 · Connections to inference systems
有系统背景的读者可以只读这一节。
| 本篇的概念 | 在推理系统里的体现 | 哪一讲 |
|---|---|---|
| 为什么要多卡 | 70B 放不下一块卡;8 块卡的带宽让每个 token 更快 | 第 6 讲 |
| NVLink 域、节点内 vs 节点间的落差 | TP 放在节点内、PP 跨节点;NVL72 扩大了 TP / EP 的范围 | 第 6、7、8 讲 |
| α–β 模型、半带宽消息 | decode 的 TP 通信受限于 α;自定义 all-reduce 内核 | 第 6、16 讲 |
| ring / 树 / 递归算法、分层、SHARP | NCCL 的算法与协议选择;多节点 all-reduce | 第 6 讲 |
| all-to-all 与负载不均 | MoE 的专家并行、冗余专家、DeepEP | 第 8、16 讲 |
| 张量并行的切法、序列并行 | Megatron 的列切 + 行切;KV 头少于卡数时复制;DP 注意力 | 第 6、8、16 讲 |
| 流水线并行 | 跨节点部署;要有足够多的微批;不降延迟 | 第 6、7 讲 |
| 上下文并行、ring attention | 长上下文的 prefill;LoongServe 的弹性序列并行 | 第 6、10 讲 |
| RDMA、GPUDirect | 解耦部署的 KV 传输;Mooncake 的传输引擎 | 第 7、9 讲 |
| PCIe、NVMe、冷启动 | KV 卸载到 CPU / SSD;模型加载 | 第 9、12 讲 |
| 计算—通信重叠 | 逐层传 KV;TBO;ping-pong;分块 prefill 与通信交错 | 第 7、8、16 讲 |
9. 小结 · Summary
- 多卡是为了放得下、算得快(带宽加起来)、服务得多;代价是通信,而卡与卡之间比卡内的 HBM 慢一个数量级以上。
- 互连有层次:NVLink 域内(每卡每方向 450 GB/s)> 节点间网卡(50 GB/s)> 以太网 > 存储。节点内的总带宽是节点对外的 9 倍。RDMA 和 GPUDirect RDMA 让网卡直接读写远端的显存。
- α–β 模型:。消息小于 时受限于延迟——优化步数和消息条数;消息大时受限于带宽——优化每个设备传的字节。
- 集合通信:all-reduce = reduce-scatter + all-gather;带宽下界是每个设备 。ring 带宽最优但步数线性,递归加倍步数对数但字节多,Rabenseifner 两头兼顾,双二叉树、交换机内归约、分层各有用处;NCCL 按消息大小和拓扑自动选择算法和协议。
- 并行方式:张量并行每层两次 all-reduce,放在 NVLink 域内;序列并行通信量相同、省激活;流水线并行通信少、不降延迟、要有足够多的微批;专家并行是 all-to-all,怕负载不均;ring attention 用环传 KV,块越长越容易藏住通信。
- 重叠:切块流水、逐层传输、两批交错能把通信藏在计算后面;切得太细会被 α 吃掉,通信比计算长时只能减少通信本身。
10. 常见误区 · Common pitfalls
- “NVLink 900 GB/s,所以传 900 MB 只要 1 毫秒”。900 GB/s 是双向合计,每个方向 450 GB/s,再打个折约 360 GB/s;小消息还要加上 α。
- “带宽高的链路,小消息也快”。小消息的时间几乎全是 α,NVLink 和 PCIe 传 1 KB 都是几微秒。
- “ring all-reduce 是最好的”。它带宽最优,但要走 步;小消息、设备多时,步数少的算法快得多。
- “加卡就能降低张量并行的延迟”。每块卡读的权重少了,但每层两次 all-reduce 的通信不随卡数减少,而且卡越多步数越多;TP 跨节点时通信会比计算还慢。
- “流水线并行能降低延迟”。它只提高吞吐;每个 token 仍然要走完所有段。
- “专家并行的通信量和张量并行一样”。decode 时它的字节少得多,难点在 α 和负载不均。
- “通信可以全部和计算重叠”。只有”下一块的计算不依赖这块的通信结果”时才能重叠;通信比计算长时最多藏住计算;通信内核还会占用 SM。
- “跨节点传数据要经过 CPU”。有 GPUDirect RDMA 时网卡直接读写显存;没有时才经主机内存中转,慢两倍以上。
11. 练习 · Exercises
练习 1(半带宽消息)。NVLink 4 的有效带宽 360 GB/s、α = 2 µs。半带宽消息多大?传 64 KB 要多久、用到了峰值带宽的百分之几?
参考答案
KB。64 KB:,有效带宽约是峰值的 8%。
练习 2(ring all-reduce)。4 块卡、每块 100 MB,在 NVLink 4 上做 ring all-reduce:每块卡发送多少字节?要几步?多久?
参考答案
每块卡发送 = 150 MB; 步;时间 (t_ring(100e6, 4, NVLINK4))。
练习 3(选算法)。16 块卡、全部走 InfiniBand(40 GB/s、α = 5 µs),all-reduce 256 KB:ring、递归加倍、Rabenseifner、二叉树各要多久?选哪个?
参考答案
ring:;递归加倍:;Rabenseifner:;二叉树(不流水):。选递归加倍:消息不大,α 的次数说了算。
练习 4(分层的收益)。代码 03 演示 3 里,4 个节点 × 8 块卡、1 GB 的 all-reduce,分层 9.61 ms、扁平的环 48.75 ms。为什么差不多是 5 倍?如果每个节点有 16 块卡呢?
参考答案
扁平的环里每一步都走网卡(40 GB/s),字节 ;分层时跨节点只传 (1/8 的数据、8 张网卡并行),节点内的两步走 NVLink(9 倍快)。主项之比大约是 ≈ ,再加上步数少,约 5 倍。每节点 16 块卡时跨节点的数据只剩 1/16,节点内的 NVLink 那两步变成主要部分,收益约 6–7 倍(可以用 t_hierarchical 算)。
练习 5(张量并行 prefill 的通信量)。Llama-3-70B、TP8,prefill 一个 4,096 token 的提示,每块卡一共要发送多少字节?
参考答案
每次 all-reduce 的数据 MB,ring 下每块卡发送 MB;每层两次 → 235 MB;80 层 → 约 18.8 GB。在 NVLink 上约 57 ms(代码 05 演示 2),所以 prefill 的通信一定要和计算重叠。
练习 6(流水线 decode)。模型切成 8 段、每段 1 ms、段间传输 0.1 ms。要让每块卡都忙起来,至少要多少个微批同时在跑?每个微批生成一个 token 的间隔至少多久?
参考答案
至少 8 个微批(段间传输让 8 个微批时利用率约 91%,再多一两个才完全填满);每个 token 的间隔至少 ms,和微批数无关(pp_decode(8, 8, 1e-3, 1e-4, 100) 给出 8.77 ms)。
练习 7(ring attention 能不能藏住通信)。一个 128K token 的提示切到 8 块卡上(每块 16K token),跨节点用 InfiniBand。按代码 04 演示 2 的估计,传 KV 能藏住吗?如果是 8K token 的提示呢?
参考答案
阈值约 2,163 个 token / 块(IB)。128K / 8 = 16K ≫ 2,163,能藏住;8K / 8 = 1K < 2,163,藏不住——短提示不值得用上下文并行。
练习 8(KV 传输)。Llama-3-70B 一个 32K token 的提示,KV 有多大?经 1 张、8 张 400 Gb/s 的网卡算完再传各要多久?逐层传输时呢?
参考答案
GB。1 张网卡约 268 ms,8 张约 33.6 ms;逐层传输时 8 张网卡只多出约 0.42 ms(代码 05 演示 3)。
12. 延伸阅读 · Further reading
- R. Thakur, R. Rabenseifner, W. Gropp. Optimization of Collective Communication Operations in MPICH. IJHPCA, 2005。集合通信算法与 α–β 代价的经典文献。
- P. Patarasuk, X. Yuan. Bandwidth Optimal All-reduce Algorithms for Clusters of Workstations. JPDC, 2009。ring all-reduce 的带宽最优性。
- Z. Hu et al. Demystifying NCCL: An In-depth Analysis of GPU Communication Protocols and Algorithms. 2025。
- M. Shoeybi et al. Megatron-LM. 2019;V. Korthikanti et al. Reducing Activation Recomputation in Large Transformer Models. 2022(序列并行)。
- Y. Huang et al. GPipe. NeurIPS 2019;H. Liu et al. Ring Attention with Blockwise Transformers for Near-Infinite Context. 2023。
- NVIDIA. DGX H100 用户指南;NVLink / NVSwitch 的技术资料;NCCL 文档。
- DeepSeek. DeepEP(专家并行的通信库,开源)。
13. 下一步 · What’s next
五篇前置讲到这里全部结束:P1 讲一块 GPU 内部,P2 讲一个模型的账,P3 讲操作系统的调度、分页和缓存,P4 讲排队和实验方法,P5 讲多块卡之间的通信。按 SYLLABUS 第 0.2 节的顺序,读完 P5 就可以进入第 6 讲(并行):它在本篇的基础上讨论 FlexFlow 的策略搜索和 Pope 等人对 Transformer 推理分区的系统分析;之后的第 7–9 讲(解耦、MoE、上下文管理)都会反复用到本篇的通信账。