4、模型显存占用分析:参数显存、梯度显存、优化器状态显存、激活值显存
显存到底被谁吃了?这是我在做模型训练时最常被问到的问题。
很多人一看到OOM(显存溢出)就慌了,要么盲目调小batch size,要么直接换卡。其实,搞清楚显存里都装了啥,你就能精准定位瓶颈。我个人习惯把模型训练时的显存占用分成四大块:参数显存、梯度显存、优化器状态显存、激活值显存。
咱们一个一个拆开看。
4.1 参数显存:模型本身的“体重”
参数显存,说白了就是模型权重占的地方。你加载一个模型,这部分就固定占上了。
计算公式很简单:
参数显存 = 参数量 × 每个参数占用的字节数
常用的精度和字节数对应关系:
| 精度类型 | 字节数 | 常见场景 |
|---|---|---|
| FP32(单精度) | 4字节 | 默认训练精度 |
| FP16(半精度) | 2字节 | 混合精度训练 |
| BF16 | 2字节 | 部分新卡支持 |
| INT8 | 1字节 | 推理量化 |
举个例子,一个7B参数的模型,用FP32加载:
7 × 10^9 × 4字节 = 28GB
嗯,这里要注意。如果你用FP16加载,那就是14GB。但很多框架会默认保留一份FP32的副本做精度累积,实际占用会翻倍。我在项目中遇到过这种情况:明明模型只有7B,用FP16算下来应该14GB,结果一跑占了28GB。查了半天,原来是框架偷偷保留了FP32的主权重。
4.2 梯度显存:反向传播的“临时账本”
梯度显存,存的是每个参数对应的梯度值。它的大小和参数显存一模一样。
为什么?因为每个参数都有一个梯度。你用FP32训练,梯度就是FP32,占4字节。你用混合精度,梯度通常也是FP32(为了数值稳定)。
所以:
梯度显存 ≈ 参数显存
你想想看,一个7B模型,参数显存28GB,梯度又占28GB。光这两项就56GB了。很多人的显存就是这么被吃掉的。
我个人习惯在显存紧张时,检查一下梯度是否真的需要全精度。有些框架支持梯度压缩,但会牺牲一点收敛速度。要不要用,得看你的场景。
4.3 优化器状态显存:Adam的“小算盘”
这一块最容易被忽略。优化器状态,就是优化器自己维护的额外变量。
以最常用的Adam优化器为例:
- 它需要保存每个参数的一阶动量(m)
- 还需要保存二阶动量(v)
- 这两个变量的大小,都和参数一样大
所以Adam的优化器状态显存 = 2 × 参数显存。
算一笔账:
7B模型,FP32训练:
参数显存:28GB
梯度显存:28GB
优化器状态:56GB(Adam)
合计:112GB
看到没?优化器状态才是真正的显存大户。我刚开始做分布式训练时,一直想不通为什么单卡跑不动7B模型。后来一算,112GB,A100 80G也扛不住啊。
4.4 激活值显存:前向传播的“中间结果”
激活值显存,存的是每一层前向计算时的中间输出。这部分最灵活,也最坑。
它的计算公式:
激活值显存 = 每层输出大小 × batch size × 层数 × 字节数
举个例子,一个Transformer模型,每层输出维度是4096,序列长度2048,batch size为4,共32层,FP16:
4096 × 2048 × 4 × 32 × 2字节 ≈ 2GB
看起来不大?但实际训练中,激活值显存会随着batch size线性增长。你把batch size从4调到8,激活值显存直接翻倍。
为什么会这样?因为反向传播时需要用到前向的中间结果来计算梯度。如果你不保存这些结果,就得重新算一遍,那就成“重计算”了。
4.5 一张图看懂显存分布
下面这张SVG图,是我根据实际项目经验画的。它展示了训练一个典型大模型时,四类显存的占比关系。
4.6 实战:如何快速估算显存
我在做模型选型时,会用一个简单的公式快速估算:
总显存 ≈ 参数显存 × (1 + 1 + 优化器系数) + 激活值显存
其中优化器系数:
- Adam:2(一阶+二阶动量)
- SGD + Momentum:1
- SGD无动量:0
举个例子,你要训练一个13B模型,用FP16 + Adam,batch size为8:
参数显存:13B × 2字节 = 26GB
梯度显存:26GB
优化器状态:26GB × 2 = 52GB
激活值显存:估算约8GB(取决于模型结构)
合计:26 + 26 + 52 + 8 = 112GB
嗯,A100 80G单卡肯定跑不了。这时候你就得考虑分布式训练或者模型并行。
4.7 避坑总结
最后,分享几个我踩过的坑:
- 别只看参数显存——优化器状态才是大头,很多人只算参数就以为能跑,结果一跑就OOM。
- 激活值显存会暴涨——特别是长序列任务。我试过把序列长度从512调到2048,激活值显存翻了4倍。
- 混合精度不是万能的——它只降参数显存,梯度还是FP32,优化器状态也还是FP32。
- 重计算要谨慎开启——虽然省显存,但训练时间可能增加30%-50%。
搞清楚这四块显存,你就能像医生一样,精准诊断显存瓶颈在哪里。是优化器状态吃太多?还是batch size太大导致激活值爆炸?对症下药,才能高效训练。