3、ZeRO核心思想:内存冗余问题,分片策略,通信与计算权衡

在数据并行训练中,最容易被忽视的成本不是算力,而是显存冗余。假设使用 8 张 GPU 训练一个 7B 参数模型,每张卡都保存一份完整的模型参数、梯度和优化器状态,那么同一份数据被复制了 8 次。ZeRO 的核心思想正是:把原本每张卡都重复保存的状态切分开,只在需要时通过通信临时聚合。它用通信换显存,用显存换可训练规模。

一、内存冗余从哪里来

以混合精度 Adam 训练为例,每个可训练参数在单卡上通常对应以下状态:

  • FP16 参数:2 字节
  • FP16 梯度:2 字节
  • FP32 主参数副本:4 字节
  • Adam 一阶动量:4 字节
  • Adam 二阶动量:4 字节

合计约 16 字节/参数。一个 7B 模型仅模型状态就约 112 GB,远超单张 80 GB 显卡容量。若再叠加激活值、临时缓冲和通信桶,显存压力会进一步放大。传统 DDP 的问题在于:每张卡都持有完整副本,显存随模型线性增长,而计算却已经被切分。

核心矛盾:数据并行把计算分到了多卡,却没有把模型状态分到多卡。ZeRO 要解决的就是这个“计算已并行、状态未并行”的错配。

二、分片策略:ZeRO-1/2/3 的递进切分

ZeRO 将模型状态分为三部分,并按阶段逐步切分:

阶段 切分对象 单卡显存节省 关键通信
ZeRO-1 优化器状态 约 4 倍 梯度 AllReduce + 参数 AllGather
ZeRO-2 优化器状态 + 梯度 约 8 倍 梯度 ReduceScatter + 参数 AllGather
ZeRO-3 优化器状态 + 梯度 + 参数 约 N 倍(N 为卡数) 前向/反向按需 AllGather 参数

ZeRO-1 只切优化器状态,参数和梯度仍保持完整副本,因此实现简单、通信增量小。ZeRO-2 进一步切梯度,反向传播时用 ReduceScatter 替代 AllReduce,每张卡只保留自己负责的那一片梯度。ZeRO-3 最彻底,连参数也切分,前向和反向计算到某一层时,才通过 AllGather 把该层参数临时拼齐,用完即释放。

ZeRO 三阶段:切分对象与通信路径 ZeRO-1 参数:完整副本 梯度:完整副本 优化器状态:分片 AllReduce 梯度 AllGather 参数 显存节省 ≈ 4× ZeRO-2 参数:完整副本 梯度:分片 优化器状态:分片 ReduceScatter 梯度 AllGather 参数 显存节省 ≈ 8× ZeRO-3 参数:分片 梯度:分片 优化器状态:分片 按需 AllGather 参数 ReduceScatter 梯度 显存节省 ≈ N× 再切梯度 再切参数

三、通信与计算的权衡

分片不是免费的。ZeRO-1 在反向传播后需要对梯度做 AllReduce,再在优化器更新后对参数做 AllGather;ZeRO-2 把 AllReduce 拆成 ReduceScatter,通信量约为原来的 1.5 倍;ZeRO-3 在前向和反向中反复 AllGather 参数,通信量进一步上升,但通过通信桶和计算重叠可以隐藏大部分开销。

关键权衡点如下:

  • 显存 vs 通信:切得越细,单卡显存越低,但跨卡通信越多。
  • 通信量 vs 重叠能力:ZeRO-3 通信量大,但可与计算流水重叠,实际吞吐未必线性下降。
  • 分片粒度 vs 实现复杂度:分片越细,参数收集、释放和生命周期管理越复杂。
  • 集群带宽:NVLink、InfiniBand 带宽越高,ZeRO-3 的收益越明显;低带宽环境可能更适合 ZeRO-1/2。
实践建议:先用 ZeRO-2 作为默认起点,它通常能在显存和通信之间取得较好平衡;当单卡显存仍不足时,再升级到 ZeRO-3,并配合 stage3_prefetch_bucket_size、stage3_param_persistence_threshold 等参数调优。

四、案例:7B 模型在 8 卡上的显存变化

假设 8 卡训练 7B 模型,单卡模型状态约 112 GB。开启不同阶段后,单卡模型状态近似变化如下:

ZeRO-1:优化器状态分片
  参数 14 GB + 梯度 14 GB + 优化器状态 84/8 ≈ 10.5 GB
  合计约 38.5 GB

ZeRO-2:优化器状态 + 梯度分片
  参数 14 GB + 梯度 14/8 ≈ 1.75 GB + 优化器状态 10.5 GB
  合计约 26.25 GB

ZeRO-3:参数 + 梯度 + 优化器状态全分片
  (14 + 14 + 84) / 8 ≈ 14 GB
  合计约 14 GB(未计激活值和临时缓冲)

可以看到,ZeRO-3 把模型状态压到了约 1/8,但代价是前向和反向中频繁的参数 AllGather。若集群带宽充足,这部分通信可以被计算掩盖;若带宽不足,训练速度可能明显下降。

五、常见误区与复盘

误区一:认为 ZeRO-3 一定比 ZeRO-2 快。实际上 ZeRO-3 通信更多,只有在显存受限或带宽充足时才有优势。
误区二:忽略激活值显存。ZeRO 主要优化模型状态,激活值仍需靠梯度检查点、序列并行等手段控制。
误区三:只调 stage 不调桶大小。通信桶过小会导致大量小消息,降低带宽利用率;过大则增加显存峰值。

复盘时建议关注三个指标:单卡显存峰值、每步通信耗时占比、吞吐量(tokens/s)。如果显存下降但吞吐骤降,说明通信未重叠好;如果显存没降多少,说明分片未生效或仍有完整副本残留。ZeRO 的本质不是“免费省显存”,而是把显存压力转化为可调度的通信与计算重叠问题。