Chapter 06

ZeRO-1 风格的 Distributed Optimizer

📌 commit 2411b02把 AdamW state 切到 DP 各 rank

nanotron 没用 DeepSpeed / Megatron-Core 的 distributed optimizer,自己实现了一个 ZeRO-1(仅切 optimizer state)。本章看它的设计。

6.1问题:Adam state 占大头

fp32 mixed precision 训练时,每个参数的内存账:

每参数 bytes
bf16 weight2
bf16 grad2
fp32 master weight4
Adam m (fp32)4
Adam v (fp32)4
合计16 bytes / param

其中 master + m + v 共 12 bytes(75%)都是 fp32 optimizer state。如果把它沿 DP 切,单卡显存减 ~75%。

6.2nanotron 的 ZeRO-1

src/nanotron/optim/zero.py(约 300 行):

class ZeroDistributedOptimizer(Optimizer):
    def __init__(self, named_params, optimizer_builder, dp_pg):
        self.dp_pg = dp_pg
        dp_size = dp_pg.size()
        dp_rank = dp_pg.rank()

        # 1) 把所有 parameter 平分到 DP rank
        self.local_params = self._shard_params(named_params, dp_rank, dp_size)

        # 2) 只为本地那份建 optimizer state
        self.optimizer = optimizer_builder(self.local_params)

    @torch.no_grad()
    def step(self):
        # 3) 每张卡只更新自己那份
        self.optimizer.step()

        # 4) all-gather 更新后的 weight
        for p_full, p_shards in self.param_groups:
            dist.all_gather(p_shards, p_local, group=self.dp_pg)

6.3shard 划分策略

nanotron 把每个 parameter 单独切(不像 DeepSpeed flatten 一坨)。具体:

6.4显存对比(7B 模型)

方案每卡 optim 占用
普通 Adam(DDP)~84 GB(全量 12 bytes/param × 7B)
ZeRO-1(DP=8)~10.5 GB
ZeRO-1(DP=64)~1.3 GB

6.5跟 ZeRO-2 / ZeRO-3 区别

等级切谁nanotron 是否支持
ZeRO-1optimizer state
ZeRO-2+ gradient未直接实现(PP 自带 grad 切)
ZeRO-3+ parameter未实现(用 TP/PP 替代)

nanotron 设计上是TP + PP + ZeRO-1,跟 Megatron 一致。要 ZeRO-3 的人通常该选 ColossalAI / DeepSpeed。

6.6启用

YAML 里:

optimizer:
  zero_stage: 1                # 1 启用 ZeRO-1;0 关闭
  weight_decay: 0.1
  clip_grad: 1.0
  optimizer_factory:
    name: adam_w
    adam_beta1: 0.9
    adam_beta2: 0.95
    adam_eps: 1.0e-8
    torch_adam_is_fused: true

6.7梯度累积时怎么办

nanotron 的 grad accumulation 在 DP all-reduce 之前:

  1. 多次 micro_batch 前向 + 反向,梯度累加到 .grad;
  2. 所有 micro_batch 跑完,再 DP all-reduce;
  3. ZeRO optimizer step。

6.8optim/ 模块源码定位

文件用途
src/nanotron/optim/base.py:28 BaseOptimizer ABC
src/nanotron/optim/gradient_accumulator.py:18 梯度累积 + FP32 主梯度 + DP allreduce
src/nanotron/optim/optimizer_from_gradient_accumulator.py把累积器和内部 optimizer 粘起来
src/nanotron/optim/zero.py ZeRO-1:optim state 分片到 DP rank
src/nanotron/optim/clip_grads.py 全局 grad norm 跨 DP/TP 合并
src/nanotron/optim/named_optimizer.py 按 name 分组(weight_decay / no_decay)
src/nanotron/optim/inherit_from_other_optimizer.py checkpoint 兼容层

6.9这章你需要带走的