跳到主内容

ZeRO 是怎么省显存的?把状态分着存

2026-10-18 发布 来源:我告诉你AI导航 阅读

大模型训练吃显存,但显存不是被模型参数一样占完的。仔细拆开,训练时要驻留显存的有三类东西:参数本身、参数的梯度、优化器状态(比如 Adam 的动量和方差)。后面两类常常比参数还占地方。ZeRO 的核心洞察就是:这三样不必每张卡都存全...

大模型训练吃显存,但显存不是被模型参数一样占完的。仔细拆开,训练时要驻留显存的有三类东西:参数本身、参数的梯度、优化器状态(比如 Adam 的动量和方差)。后面两类常常比参数还占地方。ZeRO 的核心洞察就是:这三样不必每张卡都存全,切碎了分着存,用的时候再取。本文按机制层讲法把这条线捋清。

三类训练状态各是什么

先看三类状态。参数是模型权重,梯度是反向传播算出来的误差信号,优化器状态是更新规则自己记的账。以 Adam 为例,混合精度下每个参数要配 FP16 权重、FP32 主权重、FP32 梯度,再加两个 FP32 优化器动量,一个参数实际要占十几个字节。模型一百亿参数的话,光优化器状态就是几百 GB 级别,这就是为什么要从状态本身下手。记住一个数量级感:混合精度训练下,一个参数的「状态全家桶」常是参数本身的十倍以上,优化器状态又占其中大头,所以 ZeRO 从它下手最划算。

第一级:只切优化器状态

ZeRO 第一级切的是优化器状态。进来的是各卡本地梯度,计算时每张卡只负责一部分参数的更新,把负责段的动量方差留在自己显存里。出去的是分片存放的优化器状态,显存立刻降一大截。参数和梯度仍然是每卡全量,所以第一级对通信量几乎没有额外要求,是性价比最高的一档。

第二级:梯度也分片

第二级在第一级基础上再切梯度。反向传播时,每张卡只保留自己负责那段参数的梯度,别段梯度算完即传即弃。进来的是本卡算出的梯度,传给对应负责卡后本地不留副本。出去的梯度占用也降下来,但通信模式变了,各卡之间开始按段交换数据。

第三级:参数用完即还

第三级连参数也切。前向时每张卡按需 all-gather 自己那段要用的参数,算完就把不属于自己的部分还回去;反向和更新同理,用哪段取哪段,用完即弃。进来的是分片存放的全量参数,某时刻每卡只驻留一小片;出去的是省到底的显存占用,代价是通信量明显上升,接近数据并行的量级。

三级逐层加码,切什么、留什么、通信涨多少并排看:

级别切的对象每卡常驻显存变化通信代价
第一级优化器状态参数与梯度降一大截几乎没有额外要求
第二级优化器状态、梯度参数梯度占用也降下来模式变了,各卡按段交换
第三级优化器状态、梯度、参数一小片参数省到底明显上升,接近数据并行

三级不是互斥选项,是按显存压力逐级加码。放不下且通信扛得住时,第三级能把单卡可训的模型规模推高一个档;但 ZeRO 不改模型结构,只改状态存放方式,这决定了它的适用边界——如果一层矩阵本身就塞不进单卡,得看张量并行是怎么切开一层的;模型层数太多跨机放不下,流水线并行是另一条路。日常使用中,ZeRO 常和数据并行叠加,后者管速度前者管显存。

微调场景下还有更轻的组合打法:先冻结大部分参数,再对剩下可训部分量化,配合 ZeRO 分片,消费级显卡也能动一些原本不敢想的模型,这套组合在微调的显存是怎么省的里有逐个拆解。日常同时维护 DeepSeek 和通义千问两套使用笔记也是这个思路:公共部分只存一份,各自的进展单独放,用时互取。

  • 三类状态:参数、梯度、优化器状态,后两者常比参数更占显存
  • 一级:只切优化器状态,通信几乎不变
  • 二级:再切梯度,算完即传即弃
  • 三级:参数也切,用时 all-gather,用完即还
  • 边界:单层放不下找张量并行,跨机分层找流水线并行

聊聊 ZeRO 的常见疑问

  • ZeRO 会让训练变慢吗?:一级几乎无感,二级略增通信,三级通信量接近数据并行,用不用看显存和速度怎么权衡。
  • 它和模型并行是一回事吗?:不是,模型并行改计算归属,ZeRO 只改状态存放,参数该谁算还谁算。
  • 推理阶段用得上 ZeRO 吗?:推理没有优化器状态和梯度,省显存主要靠量化与分页管理,思路不同。

反馈页面信息

请描述需要更正的地方,页面标题和网址会自动附上。

也可以发邮件至 [email protected]