想象一下,你是一座大型博物馆的馆长,手里有一批珍贵展品要摆到好几个分馆里。每件展品除了本体,还配着一本厚重的历史档案册(记录它的修复记录)和一叠玻璃上的批注贴纸(检查员的修改意见)。博物馆总有放不下东西的时候——展馆的库房(GPU 显存)永远不够用。怎么办呢?最聪明的办法不是加建库房,而是把档案册、批注、甚至展品本体分别放到不同的分馆去,谁要用谁去调阅(等用完了再还回去)。这就是 ZeRO(零冗余优化器)的核心思想:与其每个 GPU 都背着一整套“模型状态的库存”,不如把库存拆开,分配给各卡分工保管。 ZeRO 把要切的“库存”分成三层:优化器状态(档案册)、梯度(批注贴纸)、模型参数(展品本体)。Stage 1 只切档案册,Stage 2 把批注也切了,Stage 3 连展品都拆开分藏。听起来“切得越多越省”,但天下没有免费的午餐——省显存的同时,各分馆之间“调阅”展品的通信次数也变多了。这篇文章就用仓库分馆的比喻,把每个阶段省了多少、贵了多少、什么时候该选哪一档,讲得明明白白。读完你就能对着自己的模型大小和 GPU 集群,直接拍板选 Stage 1、2 还是 3。

岗位关联

对 AI 从业者来说,ZeRO 选型是分布式训练中最常见的“性价比决策”:选低了 OOM 崩溃,选高了白付通信成本。掌握这套决策逻辑,你就能在算力有限时优雅地塞进更大的模型,这是大模型工程师的基本功。

目录
  1. 可视化演示
  2. 显存三兄弟
  3. 阶段一存账本
  4. 阶段二分批注
  5. 阶段三搬展品
  6. 通信成本账
  7. 选型决策表
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示ZeRO-1/2/3各阶段显存分区节省、通信开销递增机制、模型规模与集群匹配的选型决策树,切换模式掌握分布式训练优化选型核心。

本节配有交互动效(进入视口后自动加载,约 3KB)。

ZeRO三阶段显存分区节省 ZeRO-1分区优化器状态(占显存最大),4x节省;ZeRO-2额外分区梯度,8x节省;ZeRO-3再分区参数,N_dx节省 分区策略将完整副本切分到各GPU,每卡仅存1/N的对应部分,按需All-Gather恢复 Z1: optimizer | Z2: +gradients | Z3: +parameters ZeRO通过逐步分区三类显存组件实现显存的指数级节省

显存三兄弟

先回到博物馆的库房。一件展品要想顺利展览,得有三样东西:展品本体(模型参数)、检查员写下的批注贴纸(梯度,反向传播算出来的修改方向)、以及一本厚厚的修复档案册(优化器状态,比如 Adam 优化器要记录的一阶动量和二阶动量)。每个 GPU 在训练时,都要把这“三兄弟”在显存里腾出位置。混合精度训练下,每个参数平均要吃掉 16 字节:参数本身存成 FP16 半精度副本占 2 字节,梯度也是 FP16 占 2 字节,剩下的 12 字节全是优化器状态的——4 字节 FP32 主副本、4 字节动量、4 字节方差。

“三兄弟”的体型差距一目了然:优化器账本最胖,占了总显存的四分之三。所以 ZeRO 的第一刀,就砍向这个最肥的账本;第二刀砍向第二重的批注;最后才轮到展品本体。这个“由胖到瘦”的切割顺序,决定了三个阶段的名字和演进关系。

所以当你听说“7B 模型要 112GB 模型状态显存”时,别惊讶——就是 \(16 \times 7 = 112\)(GB)。库房不够用时,馆长自然盯上最占地方的档案柜:12 字节的优化器账本。

Kall=16ψ=2ψ(参数)+2ψ(梯度)+4ψ(FP32 主副本)+4ψ(动量)+4ψ(方差)K_{\text{all}} = 16\psi = 2\psi(\text{参数}) + 2\psi(\text{梯度}) + 4\psi(\text{FP32 主副本}) + 4\psi(\text{动量}) + 4\psi(\text{方差})
这里的 \(\psi\) 是模型参数量(比如 70 亿参数的模型,\(\psi=7\times10^9\)),整个式子说明每个参数平均要消耗 16 个字节的模型状态显存,其中优化器状态占 12 字节。
  1. 认识总账单\(K_{\text{all}}\) 是单卡完整存放模型状态所需的总显存,它是参数量的 16 倍。
    Kall=16ψK_{\text{all}} = 16\psi
  2. 参数副本训练时模型参数以 FP16 半精度保存一份用于前向传播,每个参数 2 字节。
    2ψ2\psi
  3. 梯度批注反向传播算出的梯度同样以 FP16 保存,每个参数再花 2 字节。
    2ψ2\psi
  4. 优化器账本Adam 等优化器要为每个参数维护 FP32 主权重、一阶动量、二阶动量,三者各 4 字节,共 12 字节。
    4ψ+4ψ+4ψ=12ψ4\psi + 4\psi + 4\psi = 12\psi

阶段一存账本

Stage 1 的策略,就是把每个展品最厚的“档案册”从中央库房拆散,平均分到 N 个分馆。每个分馆只保管全馆档案的 \(1/N\),查资料时找对应的分馆要就行。这样一来,原本每卡要背着 16 字节/参数的完整负担,现在优化器状态那一大坨(12 字节)被切成了 N 份,每卡只需拿 \(12/N\) 字节。

公式也随之清爽:每参数显存开销从 16 字节降到了 \(4 + 12/N\) 字节。假设你有 8 张卡,那就是 \(4+1.5=5.5\) 字节/参数——比原来省了约三分之二。而且 Stage 1 的通信模式跟普通数据并行(DDP)处于同一量级,因为梯度还是要全网同步,只是同步完各卡各自更新自己手头那部分账本。用大白话说,馆长只是把档案挪了位置,展览流程基本没变,却一下子腾出了大量库房。

Stage 1 是“性价比最高的一刀”:改动最小、通信几乎不变、显存立刻瘦身。如果你只是刚开始接触分布式训练,模型在单卡上勉强能跑、只是显存吃紧,Stage 1 往往是最稳妥的入门选择。

K1=4ψ+12ψNK_1 = 4\psi + \frac{12\psi}{N}
这是 Stage 1 下每块 GPU 需要承担的模型状态显存:固定保留参数(2\(\psi\))与梯度(2\(\psi\)),优化器状态按卡数 N 平分。
  1. 固定的 4 字节参数副本和梯度是前向反向的“必需品”,每个 GPU 仍要完整持有,共 4 字节。
    4ψ=2ψ+2ψ4\psi = 2\psi + 2\psi
  2. 账本被切分12 字节的优化器状态被切成 N 份,每卡只留总数的 \(1/N\)。
    12ψN\frac{12\psi}{N}
  3. 相加得结果两者相加就是 Stage 1 的每卡显存公式。
    K1=4ψ+12ψNK_1 = 4\psi + \frac{12\psi}{N}

阶段二分批注

Stage 1 省下的空间可能还不够。馆长发现,检查员的“批注贴纸”也挺占地方的——2 字节的梯度虽然在体型上不如账本,但叠加起来依然可观。于是 Stage 2 决定:账本和批注全都分馆存放。现在每个 GPU 只需要保管 \(12/N\) 的优化器状态和 \(2/N\) 的梯度,参数本体仍然每卡留一份完整的。

每参数显存开销进一步降到 \(2 + 14/N\) 字节。8 卡场景下是 \(2+1.75=3.75\) 字节/参数,比 Stage 1 的 5.5 字节又少了近三分之一。为什么 Stage 2 能这么省?因为它把“谁算的梯度谁自己留着更新”,不再把全量梯度广播给所有人。梯度同步的方式也从“所有人拿到完整批注”变为“每人拿属于自己那部分批注”,通信量依然和 DDP 同一量级。

Stage 2 是分布式训练里最常用的“默认档位”:8 卡训练 7B 模型时,每卡模型状态仅 26GB 左右(\(3.75 \times 7\)),配上激活值和大 batch,80GB 的 A100 也游刃有余。它就像把批注贴纸也分馆之后,各分馆终于能同时并行处理自己的那部分检查工作,效率不降、空间大省。

K2=2ψ+14ψNK_2 = 2\psi + \frac{14\psi}{N}
Stage 2 下每卡显存公式:参数固定留 2\(\psi\),优化器状态与梯度加起来共 14\(\psi\) 按 N 平分。
  1. 参数仍要全量前向计算需要完整模型参数,所以每卡保留 2 字节的参数副本。
    2ψ2\psi
  2. 梯度加入切分14 代表“12 字节优化器状态 + 2 字节梯度”打包切分。
    14ψN=12ψN+2ψN\frac{14\psi}{N} = \frac{12\psi}{N} + \frac{2\psi}{N}
  3. 合起来最后得到 Stage 2 的每卡显存。
    K2=2ψ+14ψNK_2 = 2\psi + \frac{14\psi}{N}

阶段三搬展品

到了 Stage 3,馆长的决心最大:连展品本体(模型参数)也拆开,每个分馆只存 \(1/N\)。这下每参数显存直接降到 \(16/N\) 字节,8 卡时只有 2 字节——理论上显存占用和参数量直接解耦了,想训练多大的模型,只要卡够多、网络够快,就能硬撑下来。

代价是什么?前向传播时要算某一层,得先把分布在各分馆的这层参数“调阅”过来(通信原语叫 all-gather,即把分散的参数片段聚合完整);反向传播时为了算梯度,又得再调阅一次参数;算完梯度后还要把梯度“回收”到各自负责的分馆(通信原语叫 reduce-scatter,即把梯度按归属切片再汇总)。一来一回,通信量比 Stage 2 多出约 50%。在博物馆的比喻里,相当于每次办展览都要把展品从各分馆押运到中央展厅,展览结束再运回去——运一次两次没事,天天运,运输队(网络带宽)就吃不消了。

Stage 3 是“极限省显存”模式,专为大模型而生。当你的单卡连一层模型都塞不下时,Stage 3 几乎是唯一出路;但如果你的模型只有 1B 且卡很多,用 Stage 3 就是杀鸡用牛刀——省下的显存有限,多出来的通信成本却实实在在。

K3=16ψNK_3 = \frac{16\psi}{N}
Stage 3 把参数、梯度、优化器状态全部按 N 平分,每卡只承担总量的 \(1/N\),但代价是前后向传播要多次聚合参数。
  1. 三兄弟全切16 字节的完整状态被 N 张卡均分,每卡只留 \(16/N\)。
    16ψN\frac{16\psi}{N}
  2. 前向调阅每层前向计算前先用 all-gather 聚合该层完整参数。
    all-gather(参数层)\text{all-gather}(\text{参数层})
  3. 反向回收反向算完梯度后用 reduce-scatter 把各卡负责的梯度切片聚合回去。
    reduce-scatter(梯度)\text{reduce-scatter}(\text{梯度})

通信成本账

回到馆长视角,做决策前得算清楚“运输账”。普通 DDP 每次迭代要把全量梯度做一个 all-reduce(全网求和并广播),通信量约 \(2\psi\)(梯度 2 字节 × 参数量)。Stage 1 和 Stage 2 的通信量和 DDP 保持同一量级,因为梯度数据量没有膨胀,只是换了个聚合方式。Stage 3 就不同了:前向 all-gather 参数、反向再 all-gather 一次参数、随后 reduce-scatter 梯度,合计约 \(3\psi\),是 Stage 2 的 1.5 倍。

这 50% 的增量,换来了显存从“线性下降”变成“反比下降”的质变。用数据说话:8 卡时,Stage 1 每参数需 5.5 字节,Stage 2 需 3.75 字节,Stage 3 只要 2 字节。如果模型是 7B,三者每卡占用分别是 38.5GB、26.25GB、14GB——Stage 3 硬生生把模型状态压到了 DDP 的八分之一。

所以选型时,网络带宽是隐藏的裁判。如果你的集群是千兆以太网,节点间带宽只有 1Gbps 级别,跑 Stage 3 很可能会让训练变成“等快递”——GPU 算完了,参数还没运到。而如果集群有 NVLink 或 InfiniBand 高速互联,Stage 3 的额外通信成本就会被大幅稀释,变成划算的买卖。

CommStage1≈CommStage2≈2ψ,CommStage3≈3ψ\text{Comm}_{\text{Stage1}} \approx \text{Comm}_{\text{Stage2}} \approx 2\psi, \qquad \text{Comm}_{\text{Stage3}} \approx 3\psi
通信量估算:前两个阶段与 DDP 同量级,Stage 3 约为 Stage 2 的 1.5 倍。\(\psi\) 是参数量,单位为“字节 × 参数量”。
  1. 基准通信量普通 DDP 同步梯度一次 all-reduce 的通信量为 \(2\psi\)。
    Comm0=2ψ\text{Comm}_{0} = 2\psi
  2. 前两阶段持平Stage 1/2 只是把 all-reduce 拆成 reduce-scatter + 局部更新,总量不变。
    Comm1≈Comm2≈2ψ\text{Comm}_{1} \approx \text{Comm}_{2} \approx 2\psi
  3. 第三阶段倍增多出的 \(1\psi\) 来自前向和反向各一次的参数 all-gather。
    Comm3≈3ψ=1.5×Comm2\text{Comm}_{3} \approx 3\psi = 1.5 \times \text{Comm}_{2}

选型决策表

现在把决策逻辑收拢成一张三步走的表。第一步看模型体量:1B 以下的小模型,单卡显存够用就别上 ZeRO,或者用 Stage 1 求稳,省下的显存留给更大 batch。第二步看中间地带:1B~13B 的模型配 8 卡,Stage 2 是最甜的点,显存占用适中、通信几乎不涨,这也是绝大多数开源大模型微调任务的默认配置。第三步看大模型:超过 30B 的模型,单卡连参数都放不下,直接 Stage 3(必要时再加 CPU offload),别无选择。

第三步之外还有一道“网速裁决”:同样 13B 模型,在 4 张 A100 且 NVLink 互联的机器上,Stage 2 可以凑合;但如果卡数少、网络又差,硬上 Stage 3 可能比 Stage 2 更慢。可以用一个朴素公式估算每卡模型状态显存:选一个阶段,算出 \(K\) 值,再乘以模型参数量(单位十亿),得到大致 GB 数。这个数字加上激活显存,必须小于单卡显存,同时留出 20% 余量。

回到博物馆的故事:如果你的展品只有一幅画(小模型),一个分馆就够摆,何必大动干戈全城分馆?如果展品是一整套兵马俑(大模型),那就必须把每个陶俑分到不同分馆,哪怕运输队要跑断腿。ZeRO 的阶段选择,本质就是一场“库存空间 vs 运输成本”的博弈——把每一样东西都切开分掉看起来很美,但只有当你真正放不下时,才值得付出那 50% 的额外运费。

N所需≥⌈GoalBytesGPU内存×0.8−激活显存⌉N_{\text{所需}} \geq \left\lceil \frac{\text{GoalBytes}}{\text{GPU内存} \times 0.8 - \text{激活显存}} \right\rceil
选型的第一原则:先算每卡模型状态显存是否装得下,再比较通信成本;装得下时优先选低阶段,装不下才升级。
  1. 分子是总需求GoalBytes 指模型状态 + 激活 + 临时缓冲的总显存需求。
    GoalBytes\text{GoalBytes}
  2. 分母是可用空间GPU 显存打八折,再减去激活显存,得到可用于模型状态的空间。
    GPU内存×0.8−激活显存\text{GPU内存} \times 0.8 - \text{激活显存}
  3. 向上取整需要的卡数就是总需求除以单卡可用空间后向上取整。
    ⌈⋅⌉\lceil \cdot \rceil

AI 应用场景

大模型训练平台的基础设施选型

阶段:模型训练与集群资源规划

解决的问题:大模型训练工程师在申请 GPU 资源时,往往不确定该用多少张卡、开哪个 ZeRO 阶段。传统做法是靠经验猜,结果要么显存溢出(OOM)导致训练中断,要么开了过高的阶段,白付通信成本。用本文的估算方法,输入模型参数量和卡数,几分钟内就能算出各阶段每卡显存,直接对接集群调度配置。

具体案例:某团队要在 8×A100-80G 集群上训练 7B 对话模型。估算 Stage 2 每卡模型状态 26GB,加激活约 45GB,余量充足;若改用 Stage 3 反而会把单步耗时从 1.2 秒拉到 1.8 秒(通信开销增加 50%),于是果断选择 Stage 2,训练吞吐提升 30%。

低带宽环境下的微调降级策略

阶段:全参数微调(Full Fine-tuning)

解决的问题:很多企业只有千兆以太网连接的多机集群,盲目按“大模型=Stage 3”的惯例配置,结果跨节点通信成为瓶颈,训练速度惨不忍睹。需要根据实际带宽做阶段降级。

具体案例:某公司在 4 机 × 4 卡、万兆以太网环境下微调 13B 模型。直接上 Stage 3,跨机通信占每步耗时的 70%;改用 Stage 2 + 梯度累积后,虽然每卡显存从 26GB 升到 49GB,但吞吐反而提升了 2 倍——因为通信量降为原来的三分之二。

超大规模模型的极限压榨

阶段:预训练(Pretraining)

解决的问题:训练 65B 以上模型时,单卡完全放不下模型状态,必须用 Stage 3 把参数、梯度、优化器状态全部切分,并配合 CPU Offload 把优化器状态卸载到内存。

具体案例:某高校实验室用 32×A100-40G 训练 65B 模型,Stage 3 下每卡模型状态仅 \(16 \times 65 / 32 = 32.5\)GB,恰好塞进 40G 显存,再配合激活检查点(activation checkpointing)成功跑通预训练。

Python 演示

python35 行
# -*- coding: utf-8 -*-"""ZeRO 阶段选型小助手: 估算模型状态显存并推荐阶段"""G = 1024 ** 3  # 1GB 字节数  def model_state_gb(params_bn, gpus, stage):    """计算每卡模型状态显存(GB); stage 取 0/1/2/3, 0 表示 DDP 基线"""    psi = params_bn * 1e9  # 参数个数    if stage == 0:        return 16.0 * psi / G    if stage == 1:        return (4.0 + 12.0 / gpus) * psi / G    if stage == 2:        return (2.0 + 14.0 / gpus) * psi / G    return 16.0 * psi / gpus / G  def suggest(params_bn, gpus, gpu_mem, fast_net=True, activation_gb=8.0):    """给出选型建议: 返回(推荐阶段, 各阶段显存列表)"""    ests = [model_state_gb(params_bn, gpus, s) for s in range(4)]    ok = [s for s in range(1, 4) if ests[s] + activation_gb < gpu_mem * 0.8]    if not ok:        return None, ests  # 所有阶段都放不下    # 默认选最低满足的阶段; 网络差时强制不用 Stage 3    if not fast_net and 3 in ok and len(ok) > 1:        ok.remove(3)    return ok[0], ests  if __name__ == "__main__":    for params_bn, gpus, mem in [(7, 8, 80), (13, 8, 80), (65, 32, 40)]:        rec, ests = suggest(params_bn, gpus, mem, fast_net=True)        line = " | ".join(["%.1fGB" % v for v in ests])        print("params=%dG gpus=%d mem=%dG -> DDP/S1/S2/S3: %s -> 推荐 Stage %s"              % (params_bn, gpus, mem, line, rec if rec else "无"))
目的:快速估算给定模型和集群下的每卡显存,自动给出 ZeRO 阶段选型建议。
  1. def model_state_gb(params_bn, gpus, stage)核心估算函数,按 16 字节/参数的规则计算不同阶段的每卡模型状态显存。
  2. psi = params_bn * 1e9把“十亿参数”换算成具体参数个数,代入公式时保持单位一致。
  3. if stage == 0: return 16.0 * psi / GDDP 基线:每卡保存完整模型状态,16 字节 × 参数量再换算成 GB。
  4. return (4.0 + 12.0 / gpus) * psi / GStage 1 公式:4 字节固定 + 12 字节优化器状态均分。
  5. return (2.0 + 14.0 / gpus) * psi / GStage 2 公式:参数 2 字节固定,优化器+梯度共 14 字节均分。
  6. return 16.0 * psi / gpus / GStage 3 公式:全部状态均分到 N 张卡。
  7. ests = [model_state_gb(...) ]一次算出 DDP、S1、S2、S3 四档显存,方便横向对比。
  8. if ests[s] + activation_gb < gpu_mem * 0.8判断该阶段是否能装下:模型状态 + 激活值必须小于单卡显存的 80%。
  9. if not fast_net and 3 in ok and len(ok) > 1网络差时把 Stage 3 从候选里剔除,避免通信瓶颈拖慢训练。
  10. return ok[0], ests返回最低能满足的 Stage,遵循“够用就好”的选型原则。

常见误区

误区很多人觉得 Stage 3 显存省得最多,肯定是性能最好的,不管什么模型都直接配 `--zero_stage=3`。结果小模型训练不仅没变快,反而每步都慢了不少。

正解ZeRO 是用通信换显存。Stage 3 的通信量是 Stage 2 的 1.5 倍,如果模型状态本来就能放下,高阶段只会增加额外开销。正确的思路是“够用就好”:用 Stage 1/2 能装下时,就别上 Stage 3;只有单卡放不下完整参数时才考虑它。

为何常见:因为显存节省的数字很直观,而通信开销是看不见摸不着的;新手容易只盯着一项指标做决策。

误区觉得买 80G 的 A100 就能解决一切,ZeRO 是给没钱买大显存的人用的土办法。结果用 80G 卡跑 13B 全参微调照样 OOM。

正解显卡显存和价格不呈线性,80G 卡的价格可能是 40G 卡的两倍多,但省下的显存有限。ZeRO 是通过算法把显存需求按卡数均摊,8 张 40G 卡跑 Stage 3 能承载的模型,大概率比 1 张 80G 卡大得多。选型应该先算 ZeRO 账,再决定要不要升级硬件。

为何常见:人们对“加钱换配置”有路径依赖,忽略了分布式训练里“多个臭皮匠顶个诸葛亮”的规模效应。

误区以为 Stage 3 下每一层都在各卡上独立计算,不需要看到完整模型参数,因此完全不用担心显存里有大块参数。

正解Stage 3 只是“长期存储”切分,但“短期计算”仍需完整参数——前向传播每一层之前必须执行 all-gather 把该层参数聚合到当前卡上,算完再释放。所以运行期显存峰值依然会短暂出现完整的一层参数,只是不长期占用。

为何常见:把“存储”和“计算”两个概念混淆了,以为切分存储就等于切分计算。

误区认为反正都是多卡训练,通信无非是同步一下梯度,Stage 1/2/3 差距不大。

正解Stage 1/2 的通信量与 DDP 同量级,但 Stage 3 因为前后向都要重新聚合参数,通信量约为 Stage 2 的 1.5 倍。在千兆以太网环境,这 50% 的增量可能让训练速度直接腰斩。

为何常见:直觉上“参数切分”只是存储变化,没意识到前向计算需要完整参数这一硬约束,自然忽略聚合参数的通信成本。

误区常常听到 Stage 3 + Offload、ZeRO-Offload 等名词,误以为 Offload 是 Stage 4,是比 Stage 3 更强力的切分方案。

正解Offload 是另一个维度的技术:把优化器状态或参数从 GPU 显存搬到 CPU 内存(甚至 NVMe 硬盘),与 ZeRO 的阶段切分相互正交。ZeRO-Offload 基于 Stage 2,而 Stage 3 + Offload 则是两套技术叠加。选型时要把“切分维度”和“卸载维度”分开考虑。

为何常见:技术名词叠加让新手误以为存在线性升级关系,实际上它们是两个独立的设计轴。

面试题

Q1. ZeRO Stage 1 主要切分了哪部分冗余?

单选题 · easy

  • A.优化器状态← 正确答案
  • B.梯度张量
  • C.模型参数
  • D.中间激活

答案:A。Stage 1 只切分优化器状态(12 字节/参数的大头);梯度要等到 Stage 2 才切,模型参数要到 Stage 3 才切。就像先搬最沉的档案柜,而不是先动展品。

Q2. 混合精度训练下,每个参数平均消耗约 16 字节模型状态显存,其中占比最大的是?

单选题 · mid

  • A.约 4 字节的参数副本
  • B.约 8 字节的梯度总和
  • C.约 12 字节的优化器状态← 正确答案
  • D.约 16 字节的激活缓存

答案:C。FP32 主权重 4 字节 + Adam 动量 4 字节 + 方差 4 字节,共 12 字节;参数和梯度各 2 字节。优化器状态最肥,所以 ZeRO 先切它。

Q3. Stage 2 相比 Stage 1 额外切分了什么?

单选题 · mid

  • A.前向用的全部层参数
  • B.反向算出的梯度← 正确答案
  • C.学习率与动量表
  • D.中间激活缓存

答案:B。Stage 1 只切优化器状态,Stage 2 把反向传播算出的梯度也按卡切分(14 字节均分)。参数要等到 Stage 3 才切,学习率调度器不参与 ZeRO 切分。

Q4. Stage 3 训练时,前向和反向传播中可能频繁出现哪些通信操作?

多选题 · mid

  • A.all-gather 聚合层参数← 正确答案
  • B.reduce-scatter 汇总梯度切片← 正确答案
  • C.point-to-point 权重单点交换
  • D.broadcast 广播全部参数

答案:AB。Stage 3 前向每层前 all-gather 参数,反向算完梯度后 reduce-scatter 梯度切片。它不采用单点交换,也不广播全部参数,而是分散聚合。

Q5. Stage 3 的通信量约为 Stage 2 的多少倍?

单选题 · hard

  • A.0.5 倍
  • B.1 倍
  • C.1.5 倍← 正确答案
  • D.3 倍

答案:C。Stage 2 通信量约 \(2\psi\),Stage 3 因前后向各聚合一次参数并 reduce-scatter 梯度,合计约 \(3\psi\),即 1.5 倍。这 50% 的增量是选型时的重要权衡。

Q6. 8 张 A100-80G 训练 13B 模型,最稳妥的 ZeRO 配置是?

单选题 · mid

  • A.Stage 1 即可
  • B.Stage 2 勉强可用
  • C.Stage 3 更稳妥← 正确答案
  • D.无需 ZeRO 直接跑

答案:C。Stage 2 下每卡模型状态约 49GB,加激活和缓冲逼近 80G 上限;Stage 3 每卡约 26GB,余量充足。单卡放不下完整状态时优先考虑 Stage 3,同时注意网络带宽。

Q7. 公式 \(4 + 12/N\)(字节/参数)对应哪个阶段的每卡显存?

单选题 · easy

  • A.Stage 1← 正确答案
  • B.Stage 2
  • C.Stage 3
  • D.DDP 基线

答案:A。4 字节是固定的参数+梯度,12/N 是切分后的优化器状态。Stage 2 应是 \(2 + 14/N\),Stage 3 是 \(16/N\)。

Q8. 选择 ZeRO 阶段时,以下哪些因素应该纳入考虑?

多选题 · hard

  • A.模型参数量与 GPU 数量← 正确答案
  • B.集群网络带宽← 正确答案
  • C.优化器类型← 正确答案
  • D.训练框架的版本号

答案:ABC。参数量和卡数决定每卡显存,带宽决定 Stage 3 的通信代价是否可承受,优化器类型影响状态字节数(如 SGD 无二阶动量只有 8 字节)。框架版本号不影响 ZeRO 的数学原理。

Q9. Stage 3 在 N 张卡下,每参数模型状态显存为?

单选题 · easy

  • A.16/N 字节← 正确答案
  • B.4+12/N 字节
  • C.2+14/N 字节
  • D.恒为 16 字节

答案:A。Stage 3 把参数、梯度、优化器状态全部切分,16 字节总账按 N 平均分。因此卡越多单卡压力越小,这也是它能训练超大规模模型的原因。

Q10. 关于 ZeRO 的说法,哪些是正确的?

多选题 · hard

  • A.小模型多卡时升级阶段收益递减← 正确答案
  • B.Stage 3 通信量约为 Stage 2 的 1.5 倍← 正确答案
  • C.Stage 3 运行期仍需临时聚合参数← 正确答案
  • D.阶段越高级训练速度一定越快

答案:ABC。小模型本身占显存小,切分收益有限且通信成本突出;Stage 3 通信更高且运行时仍需 all-gather 参数。D 把通信成本忽略了,高阶段省显存不代表训练更快。