返回课堂

ZeRO-3:省下副本之后,怎样算完一层?

E04/b0 · 1 · 每卡仍跑全部层

ZeRO-3 · 一层的教学调度:用后释放完整参数,反向按需重新收集

GPU 0 · 数据 A

持有分片 θ0
主权重+动量
仅保留所属分片
无本层完整副本

本卡数据:L₁ → … → Lₙ

GPU 1 · 数据 B

持有分片 θ1
主权重+动量
仅保留所属分片
无本层完整副本

本卡数据:L₁ → … → Lₙ

GPU 2 · 数据 C

持有分片 θ2
主权重+动量
仅保留所属分片
无本层完整副本

本卡数据:L₁ → … → Lₙ

GPU 3 · 数据 D

持有分片 θ3
主权重+动量
仅保留所属分片
无本层完整副本

本卡数据:L₁ → … → Lₙ

每卡自己的数据,都要经过全部层

真实预取、驻留与重叠策略会改变时序和峰值;这不是把不同层永久分配给不同卡。

1 · 每卡仍跑全部层

先锁定一个不会变的条件:四张卡各有自己的数据,每一份数据仍要经过模型的全部层。我们现在跟踪其中一层,并不把第一层永久交给第一张卡、第二层永久交给第二张卡。图上的四种颜色表示这个层的参数分片归谁保存。

教师备课:指图与模拟问答

指图与推进 · 不朗读教师指向当前高亮对象,随后推进。

E04/b1 · 2 · 临用时收集

ZeRO-3 · 一层的教学调度:用后释放完整参数,反向按需重新收集

GPU 0 · 数据 A

持有分片 θ0
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

数据始终留在本卡计算

GPU 1 · 数据 B

持有分片 θ1
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

数据始终留在本卡计算

GPU 2 · 数据 C

持有分片 θ2
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

数据始终留在本卡计算

GPU 3 · 数据 D

持有分片 θ3
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

数据始终留在本卡计算

all-gather:各卡参数分片 → 每卡本层完整视图

真实预取、驻留与重叠策略会改变时序和峰值;这不是把不同层永久分配给不同卡。

2 · 临用时收集

轮到这一层时,四张卡交换它们负责的分片,于是每张卡都临时拥有这一层的完整参数。这叫 all-gather,中文可以直接理解为收集到完整视图。箭头送来的是本层需要的参数,不要求一次把全模型所有层都聚齐。

教师备课:指图与模拟问答

指图与推进 · 不朗读教师指向当前高亮对象,随后推进。

E04/b2 · 3 · 本地前向

ZeRO-3 · 一层的教学调度:用后释放完整参数,反向按需重新收集

GPU 0 · 数据 A

持有分片 θ0
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

本地前向:输入 → 输出

GPU 1 · 数据 B

持有分片 θ1
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

本地前向:输入 → 输出

GPU 2 · 数据 C

持有分片 θ2
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

本地前向:输入 → 输出

GPU 3 · 数据 D

持有分片 θ3
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

本地前向:输入 → 输出

本层完整参数 × 本卡输入 → 下一层激活

真实预取、驻留与重叠策略会改变时序和峰值;这不是把不同层永久分配给不同卡。

3 · 本地前向

现在材料齐了,各卡就可以用完整本层参数处理自己的输入,产生交给下一层的中间结果。我们把这些中间结果叫激活。然后按同样办法继续后面的层,最终形成各卡数据对应的损失。参数相同不意味着激活相同,因为各卡读的数据不同。

教师备课:指图与模拟问答

指图与推进 · 不朗读教师指向当前高亮对象,随后推进。

E04/b3 · 4 · 释放临时完整参数

ZeRO-3 · 一层的教学调度:用后释放完整参数,反向按需重新收集

GPU 0 · 数据 A

持有分片 θ0
主权重+动量
仅保留所属分片
无本层完整副本

释放临时完整视图

GPU 1 · 数据 B

持有分片 θ1
主权重+动量
仅保留所属分片
无本层完整副本

释放临时完整视图

GPU 2 · 数据 C

持有分片 θ2
主权重+动量
仅保留所属分片
无本层完整副本

释放临时完整视图

GPU 3 · 数据 D

持有分片 θ3
主权重+动量
仅保留所属分片
无本层完整副本

释放临时完整视图

用后释放完整视图;所属参数分片仍保存

真实预取、驻留与重叠策略会改变时序和峰值;这不是把不同层永久分配给不同卡。

4 · 释放临时完整参数

本例采用最容易看清节省来源的策略:本层前向算完,就释放刚才临时收齐的完整参数,只保留自己负责的分片。因此全模型没有在每卡长期变回完整副本。代价也已经埋下:一会儿反向如果还需要这些参数,我们要再收集一次。

教师备课:指图与模拟问答

指图与推进 · 不朗读教师指向当前高亮对象,随后推进。

E04/b4 · 5 · 反向再收集并计算

ZeRO-3 · 一层的教学调度:用后释放完整参数,反向按需重新收集

GPU 0 · 数据 A

持有分片 θ0
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

本地反向:计算参数梯度

GPU 1 · 数据 B

持有分片 θ1
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

本地反向:计算参数梯度

GPU 2 · 数据 C

持有分片 θ2
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

本地反向:计算参数梯度

GPU 3 · 数据 D

持有分片 θ3
主权重+动量
↓
本层完整参数
θ₀ θ₁ θ₂ θ₃

本地反向:计算参数梯度

反向需要时再 all-gather,然后计算本地梯度

真实预取、驻留与重叠策略会改变时序和峰值;这不是把不同层永久分配给不同卡。

5 · 反向再收集并计算

前向走完后,从损失沿层往回传播。轮到这一层时,再次收集本层参数,用它和反向传来的信息计算梯度。这里画了第二次收集,是为了让通信代价真实可见。工程上可以预取或者延迟释放,但那又会改变峰值内存;没有一种图能同时免费省掉所有存储与通信。

教师备课:指图与模拟问答

指图与推进 · 不朗读教师指向当前高亮对象,随后推进。

E04/b5 · 6 · 梯度归约到负责人

ZeRO-3 · 一层的教学调度:用后释放完整参数,反向按需重新收集

GPU 0 · 数据 A

持有分片 θ0
主权重+动量
↑
本卡负责的
归约后梯度 g0

数据始终留在本卡计算

GPU 1 · 数据 B

持有分片 θ1
主权重+动量
↑
本卡负责的
归约后梯度 g1

数据始终留在本卡计算

GPU 2 · 数据 C

持有分片 θ2
主权重+动量
↑
本卡负责的
归约后梯度 g2

数据始终留在本卡计算

GPU 3 · 数据 D

持有分片 θ3
主权重+动量
↑
本卡负责的
归约后梯度 g3

数据始终留在本卡计算

reduce-scatter:汇总梯度 → 发给各片负责人

真实预取、驻留与重叠策略会改变时序和峰值;这不是把不同层永久分配给不同卡。

6 · 梯度归约到负责人

四张卡各算出了本地数据的贡献。接下来先把对应梯度汇总,再把合并后的各段发到负责那一段参数的卡。这叫 reduce-scatter:归约后分片。它不是随便分走四份未经合并的梯度;每个最终分片都包含四份数据的贡献,平均方式仍遵守训练的约定。

教师备课:指图与模拟问答

指图与推进 · 不朗读教师指向当前高亮对象,随后推进。

E04/b6 · 7 · 更新本卡状态

ZeRO-3 · 一层的教学调度:用后释放完整参数,反向按需重新收集

GPU 0 · 数据 A

持有分片 θ0
主权重+动量 已更新
仅保留所属分片
无本层完整副本

仅更新自己负责的片

GPU 1 · 数据 B

持有分片 θ1
主权重+动量 已更新
仅保留所属分片
无本层完整副本

仅更新自己负责的片

GPU 2 · 数据 C

持有分片 θ2
主权重+动量 已更新
仅保留所属分片
无本层完整副本

仅更新自己负责的片

GPU 3 · 数据 D

持有分片 θ3
主权重+动量 已更新
仅保留所属分片
无本层完整副本

仅更新自己负责的片

用归约梯度更新所属状态,进入下一次训练

真实预取、驻留与重叠策略会改变时序和峰值;这不是把不同层永久分配给不同卡。

7 · 更新本卡状态

最后各卡只更新自己负责的主权重和动量,并得到新的工作参数分片。下一轮收集时,拿到的就是更新后的参数。这一圈走完,节省从哪里来、通信为什么出现,就连在一起了。DeepSpeed ZeRO、PyTorch 的全分片数据并行 FSDP,是可以使用的工程路线;具体预取和驻留不同,不能当成逐细节相同的软件。接下来我们换一种切法:直接把计算分给不同设备。

教师备课:指图与模拟问答

指图与推进 · 不朗读教师指向当前高亮对象,随后推进。

补充推导、边界与来源

这里展示“算完即释放完整层参数”的教学调度。每张数据并行卡都有自己的输入,并依次执行全部层。计算某层前,通过 all-gather 汇集该层分片;本地前向完成后释放临时完整参数,保留所属分片。全网前向形成损失以后,反向沿层返回,需要时再次收集该层参数,计算本地梯度;reduce-scatter 将跨数据卡的梯度汇总并分给相应所有者;各卡更新自己负责的主权重、动量与工作参数分片。

all-gather 是“把各处分片拼成完整视图”,reduce-scatter 是“先合并贡献,再分开保留结果”。实际实现可能预取、复用或延长参数驻留以换取通信效率,所以 32 GB 不代表峰值。DeepSpeed ZeRO 与 PyTorch FSDP 都可用于这类分片训练,但具体策略需按实现和版本核对。

本页证据与条件

A19;A22;A23;P11

进入主题正文