λLLM Wiki

Ring AllReduce Walkthrough

本页以一个具体数值示例,逐轮展示 Ring AllReduce 的 Reduce-Scatter 和 All-Gather 两个阶段。

设定

3 个 GPU 排成环形:GPU 0 → GPU 1 → GPU 2 → GPU 0

每个 GPU 持有一个 6 元素向量,均分为 3 个 chunk(每 chunk 2 个元素):

Chunk 0Chunk 1Chunk 2
GPU 0[1, 2][3, 4][5, 6]
GPU 1[7, 8][9, 10][11, 12]
GPU 2[13, 14][15, 16][17, 18]

目标:每个 GPU 都得到全部元素之和 [21, 24, 27, 30, 33, 36]

阶段一:Reduce-Scatter(N1=2N-1 = 2 轮)

每轮中,每个 GPU 向右邻居发送一个 chunk,同时从左邻居接收一个 chunk 并累加到本地。

Round 1

每个 GPU 发送自己”负责”的 chunk,接收左邻居的 chunk 并累加:

GPU发送 → 右邻居从左邻居接收累加到本地 chunk
GPU 0Chunk 0 [1, 2] → GPU 1Chunk 2 [17, 18] from GPU 2Chunk 2: [5+17, 6+18] = [22, 24]
GPU 1Chunk 1 [9, 10] → GPU 2Chunk 0 [1, 2] from GPU 0Chunk 0: [7+1, 8+2] = [8, 10]
GPU 2Chunk 2 [17, 18] → GPU 0Chunk 1 [9, 10] from GPU 1Chunk 1: [15+9, 16+10] = [24, 26]

Round 1 后的状态(粗体为累加后的 chunk):

Chunk 0Chunk 1Chunk 2
GPU 0[1, 2][3, 4][22, 24]
GPU 1[8, 10][9, 10][11, 12]
GPU 2[13, 14][24, 26][17, 18]

Round 2

每个 GPU 发送上一轮刚累加过的 chunk:

GPU发送 → 右邻居从左邻居接收累加到本地 chunk
GPU 0Chunk 2 [22, 24] → GPU 1Chunk 1 [24, 26] from GPU 2Chunk 1: [3+24, 4+26] = [27, 30]
GPU 1Chunk 0 [8, 10] → GPU 2Chunk 2 [22, 24] from GPU 0Chunk 2: [11+22, 12+24] = [33, 36]
GPU 2Chunk 1 [24, 26] → GPU 0Chunk 0 [8, 10] from GPU 1Chunk 0: [13+8, 14+10] = [21, 24]

Reduce-Scatter 结果

每个 GPU 恰好持有一个完整归约的 chunk:

GPU负责的 Chunk
GPU 0Chunk 1[27, 30]
GPU 1Chunk 2[33, 36]
GPU 2Chunk 0[21, 24]

验证:21+24+27+30+33+36 = 1+2+...+18 = 171

阶段二:All-Gather(N1=2N-1 = 2 轮)

现在每个 GPU 持有完整结果的 1/31/3,需要通过 All-Gather 让所有 GPU 都拥有完整结果。操作与 Reduce-Scatter 类似,但接收后直接覆盖而非累加。

Round 1

GPU发送 → 右邻居从左邻居接收 → 覆盖本地
GPU 0[27, 30] → GPU 1[21, 24] from GPU 2 → 覆盖 Chunk 0
GPU 1[33, 36] → GPU 2[27, 30] from GPU 0 → 覆盖 Chunk 1
GPU 2[21, 24] → GPU 0[33, 36] from GPU 1 → 覆盖 Chunk 2

Round 1 后(✅ 表示已拥有完整归约值):

Chunk 0Chunk 1Chunk 2
GPU 0[21, 24][27, 30]
GPU 1[27, 30][33, 36]
GPU 2[21, 24][33, 36]

Round 2

GPU发送 → 右邻居从左邻居接收 → 覆盖本地
GPU 0[21, 24] → GPU 1[33, 36] from GPU 2 → 覆盖 Chunk 2
GPU 1[27, 30] → GPU 2[21, 24] from GPU 0 → 覆盖 Chunk 0
GPU 2[33, 36] → GPU 0[27, 30] from GPU 1 → 覆盖 Chunk 1

最终结果

Chunk 0Chunk 1Chunk 2拼接
GPU 0[21, 24][27, 30][33, 36][21, 24, 27, 30, 33, 36]
GPU 1[21, 24][27, 30][33, 36][21, 24, 27, 30, 33, 36]
GPU 2[21, 24][27, 30][33, 36][21, 24, 27, 30, 33, 36]

所有 GPU 持有相同的完整归约结果。

通信量统计

整个过程中,每个 GPU:

  • Reduce-Scatter:发送 2 个 chunk × 2 元素 = 4 个元素
  • All-Gather:发送 2 个 chunk × 2 元素 = 4 个元素
  • 总计:8 个元素

公式验证:2(N1)N×D=2×23×6=8\frac{2(N-1)}{N} \times D = \frac{2 \times 2}{3} \times 6 = 8

相关页面

  • AllReduce 算法总览见 allreduce
  • FSDP 如何使用 Reduce-Scatter 和 All-Gather 见 fsdp

Comments