通信 101:GPU 之间怎么传数据

128 GB 的 model state 单卡放不下,只能上多卡,于是多出一笔新开销:卡与卡之间传数据(communication)。这一课讲几种标准传法(collective)各做什么、每张卡要发多少、在 NVLink 和 InfiniBand 上各要多久。下一课的 DDP 和 ZeRO 全靠它。

面试会这样问How much data does each GPU send in a ring all-reduce? · What are all-reduce, reduce-scatter, all-gather and all-to-all, and where is each used? · What is RDMA, and what does GPUDirect RDMA skip?

考过NVIDIA Research System AI 实习 2024 一面("先问了一些基础知识,包括分布式训练,RDMA的工作流程和编程,网络的一些知识",1p3a 1060932)· 阿里淘天("有4块卡,数据被切成了4份…设一次通信量是x,如果要实现一次All Reduce操作,需要多少通信量?")· 阿里("NCCL中Ring AllReduce、Tree AllReduce的工作原理")· Anthropic Perf/Infra 技术电面(10 个 node 求 distributed mode 和 median,讨论用哪种 collective、tree 还是 ring,1p3a 1188498)

为什么卡之间非“说话”不可

多卡训练只有两种切法,哪种都要传数据:

传数据时 GPU 常常只能干等,所以要少搬,或者边算边搬(overlap)。

三种距离:厨房、楼、货车

后面每一课都在想办法让重的通信留在楼里。

五个常用的 collective(外加 broadcast)

collective 是一组卡一起参与的通信操作,面试直接说英文名。rank 是卡的编号。下面都用 2 张卡举例:rank0 有 (1, 2),rank1 有 (3, 4)。

collective做什么例子的结果谁在用
all-reduce对应位置求和,每张卡都拿到完整的和两张卡都得到 (4, 6)DDP 同步 gradient;TP 合并部分和
reduce-scatter也求和,但每张卡只拿和的 1/Nrank0 得 4,rank1 得 6ZeRO、FSDP 同步 gradient;SP(第 5 课)
all-gather每张卡出一块,拼成完整的,发给所有卡rank0 出 4、rank1 出 6 → 两张卡都得到 (4, 6)ZeRO、FSDP 拼回 parameter;SP
all-to-all每张卡把第 j 块发给 rank j,只交换、不求和rank0 得 (1, 3),rank1 得 (2, 4)MoE 把 token 送到 expert(EP)
send / recv一张卡发、一张卡收,点对点rank0 把 (1, 2) 发给 rank1PP 在相邻 stage 之间传 activation
broadcast把一张卡的数据复制给所有卡两张卡都是 (1, 2)DDP 开始时把 rank0 的初始 weight 发给大家

第 2、3 行连起来就是第 1 行。这是这一课最重要的等式:all-reduce = reduce-scatter + all-gather。第 4 课的 ZeRO 就是在这两步中间插了一步。

ring all-reduce:4 张卡围成一圈

最笨的做法是全发给 GPU0,加完再发回去。GPU0 要收 3 份、发 3 份,瓶颈全压在它一张卡上。ring 让 4 张卡围成一圈,gradient 切成 4 块,每一步每张卡只给右边的邻居发 1 块,所有链路同时在用,像传送带。每一步的数值见 6.12 的图。

每张卡发了多少:6 步,每步 1/4 份,一共 1.5 份。一般地,N 张卡、数据大小 S:

\[ \text{每卡发送} = 2(N-1)\cdot\frac{S}{N} = \frac{2(N-1)}{N}\,S \]

N = 4、8、32 时分别是 1.5S、1.75S、1.94S,不超过 2S,几乎和卡数无关。单独做一次 reduce-scatter 或 all-gather 是它的一半,\((N-1)S/N\)。

ring 和 tree

ring 发的数据最少,但要走 \(2(N-1)\) 步,每步都有固定的 latency,1024 张卡要 2046 步。tree 沿二叉树往上加、再往下发,只要约 \(2\log_2 N\) 步,1024 张卡约 20 步。所以数据大用 ring,数据小、卡又多用 tree。

粗算:8B 的 gradient 同步一次要多久

8B 模型的 bf16 gradient 是 S = 16 GB。时间 = 每卡发送量 ÷ 链路 bandwidth:

场景每卡发送链路时间
一台机器 8 张卡2 × 7/8 × 16 = 28 GBNVLink 450 GB/s≈ 62 ms
4 台机器 32 张卡,每一跳都按 IB 算2 × 31/32 × 16 = 31 GBIB 50 GB/s≈ 620 ms
4 台机器 32 张卡,分层做机内 14 GB → 跨机 3 GB → 机内 14 GBNVLink → IB → NVLink≈ 31 + 60 + 31 ≈ 120 ms

第二行偏悲观,真实的通信库会像第三行那样按拓扑分层。先在机内 reduce-scatter,每张卡只剩 1/8(2 GB),跨机只对这 2 GB 做 all-reduce(2 × 3/4 × 2 = 3 GB),最后在机内 all-gather。准确的数要用 nccl-tests 实测。这笔时间还要藏到 backward 后面,见第 4 课。

NCCL:真正干这些活的库

NCCL(NVIDIA Collective Communications Library,读作 “nickel”)是 NVIDIA 的 GPU 通信库,实现了上面所有 collective。PyTorch 里写 dist.init_process_group(backend="nccl"),DDP、FSDP、DeepSpeed、Megatron 底下都是它。它会自己探测拓扑,机内走 NVLink,跨机走 IB,再按数据大小和卡数选 ring 或 tree。

RDMA 和 GPUDirect:货车直接开到仓库门口

普通网络(TCP)跨机传数据,GPU 的数据要先拷到 CPU 的内存(host memory),再由操作系统 kernel 打包交给网卡,对面再反着来一遍。好比货要先从厨房搬到楼下收发室,登记、重新装箱才能上车。

写 RDMA 程序用的接口叫 verbs,流程记四步:

  1. register memory:把 buffer 登记给网卡并 pin 住(不许 OS 挪走),拿到 lkey、rkey,对面要有 rkey 才能读写它
  2. 建连接:创建 queue pair(QP)和 completion queue(CQ),和对面交换 QP 编号、内存地址和 rkey
  3. 下单:往 QP 里 post 一个 work request,可以是 send / recv,也可以直接 RDMA write / read 对面的内存
  4. 等完成:网卡做完往 CQ 里放一条完成记录,程序 poll CQ 就知道传完了

去查一下你在 TikTok 的 32 卡 job 跨了 4 台机器,DeepSpeed 底下就是 NCCL。可以查清楚:集群是 InfiniBand 还是 RoCE?每台机器几张网卡?如果日志开过 NCCL_DEBUG=INFO,启动时会打印走的是 NET/IB 还是 NET/Socket,有没有 GDRDMA 字样(说明用上了 GPUDirect RDMA)。面试官问“跨机走什么网络”时,你能说出具体硬件。

30 秒英文回答

Once the model or the data is split, GPUs exchange data through collectives. All-reduce sums a tensor and leaves the result on every GPU; DDP uses it for gradients. Reduce-scatter leaves each GPU one summed shard, all-gather reassembles the shards, and together they equal an all-reduce, which ZeRO and FSDP exploit. MoE routes tokens with all-to-all, and pipeline stages use send and recv. Ring all-reduce does a reduce-scatter then an all-gather, N minus 1 steps each, so every GPU sends 2(N−1)/N times the data: bandwidth-optimal, but latency grows with N, so NCCL uses trees for small messages. Across nodes, GPUDirect RDMA lets the NIC read GPU memory directly.

自测

4 张卡,数据切成 4 份,每卡 x,ring all-reduce 每卡要发多少?(阿里淘天原题)

6 步,每步发 x/4,共 1.5x,也就是 \(2(N-1)/N \cdot x\)。

RDMA 的工作流程是什么?(NVIDIA Research System AI 实习 2024)

register memory → 建 QP 和 CQ 并交换 rkey → post work request → poll CQ 等完成。

ring 每卡的通信量几乎和卡数无关,那卡多了为什么还会慢?

一是步数 \(2(N-1)\) 随卡数线性增长,每步都有固定 latency。二是一圈的速度取决于最慢的那条边,跨机的 IB 比 NVLink 慢 9 倍。

MoE 为什么用 all-to-all,不用 all-reduce?

每个 token 要去的 expert 不一样,要做的是把不同的数据送到不同的卡,不是求和。

ZeRO、FSDP 为什么用 reduce-scatter 同步 gradient,不用 all-reduce?

每张卡只负责更新 1/N 的 parameter,只需要这 1/N 的 gradient 总和。reduce-scatter 正好给出这一份,发的量只有 all-reduce 的一半。