面试-训练显存占用估计

5. 训练显存占用

极简公式:

text 复制代码
训练总显存 =
模型权重显存
+ 梯度显存
+ 优化器状态显存
+ 前向激活值显存
+ 临时 buffer / CUDA runtime / 显存碎片

和推理最大的区别是:训练不仅要存模型,还要存梯度、优化器状态,并且激活值不能立刻释放,因为反向传播要用。


5.1 全参数训练显存

一句话: 全参数训练 = 权重 + 梯度 + 优化器状态 + 激活值。

以 BF16 训练、AdamW 优化器为例:

1)模型权重
text 复制代码
模型权重 = 参数量 × 2 byte

Qwen3-1.7B:

text 复制代码
1.7B × 2 byte ≈ 3.4GB
2)梯度显存

每个可训练参数都要保存梯度。

text 复制代码
梯度 = 参数量 × 2 byte

所以:

text 复制代码
1.7B × 2 byte ≈ 3.4GB
3)AdamW 优化器状态

AdamW 通常为每个参数维护:

text 复制代码
m 一阶动量
v 二阶动量

很多训练框架中 optimizer state 默认是 FP32:

text 复制代码
AdamW状态 ≈ 参数量 × 2 × 4 byte

所以:

text 复制代码
1.7B × 2 × 4 byte ≈ 13.6GB

如果还保留 FP32 master weight,则还要额外:

text 复制代码
1.7B × 4 byte ≈ 6.8GB
4)激活值显存

训练时激活值是大头之一。

推理时:

python 复制代码
with torch.no_grad():
    out = model(x)

中间激活可以尽快释放。

训练时不能这样,因为反向传播需要:

text 复制代码
前向每层保存激活值 → 反向时用这些激活值计算梯度

激活值大致和下面因素正相关:

text 复制代码
batch_size × seq_len × hidden_size × 层数 × dtype字节数

并且 Attention 中间矩阵还会受到:

text 复制代码
batch_size × num_heads × seq_len × seq_len

影响。

所以训练时 seq_len 一旦变长,显存上涨非常明显。


5.2 全参数训练示例:Qwen3-1.7B

假设:

text 复制代码
BF16 全参数训练
AdamW
batch=1
seq_len=2048
不开 ZeRO
不开 gradient checkpointing

估算:

text 复制代码
权重:        3.4GB
梯度:        3.4GB
Adam状态:    13.6GB
激活值:      4GB ~ 8GB
CUDA开销:    0.5GB ~ 1GB

总计:

text 复制代码
约 25GB ~ 30GB+

如果保留 FP32 master weight:

text 复制代码
再加约 6.8GB
总计可能到 32GB ~ 38GB+

所以 2B 级模型推理可能 6GB 左右能跑,但全参数训练通常需要 24GB 以上,长序列或大 batch 会继续上涨。


6. LoRA / QLoRA 训练显存

6.1 LoRA 显存为什么小

LoRA 的核心思想:

text 复制代码
冻结原模型参数,只训练少量低秩矩阵 A 和 B

原来的线性层:

text 复制代码
y = W x

LoRA 后:

text 复制代码
y = W x + B A x

其中:

text 复制代码
W 冻结,不更新
A、B 可训练

所以 LoRA 不需要为全模型参数保存梯度和 Adam 状态,只需要为 LoRA 参数保存。


6.2 LoRA 训练显存公式

text 复制代码
LoRA训练总显存 =
基础模型权重显存
+ LoRA参数显存
+ LoRA梯度显存
+ LoRA优化器状态显存
+ 激活值显存
+ runtime开销

重点区别:

text 复制代码
全参数训练: 梯度和优化器状态覆盖整个模型
LoRA训练: 梯度和优化器状态只覆盖 LoRA 小参数

LoRA 参数量通常只占原模型的:

text 复制代码
0.1% ~ 2%

所以优化器状态显存会小很多。


6.3 LoRA 示例:Qwen3-1.7B

假设:

text 复制代码
基础模型 BF16
LoRA rank=8/16/32
batch=1
seq_len=2048

估算:

text 复制代码
基础模型权重:      3.4GB
LoRA参数+梯度:     几十 MB ~ 几百 MB
LoRA优化器状态:    几十 MB ~ 几百 MB
激活值:            4GB ~ 8GB
CUDA开销:          0.5GB ~ 1GB

总计大约:

text 复制代码
8GB ~ 13GB

注意:LoRA 虽然大幅减少「梯度 + 优化器状态」,但不会自动消灭训练激活值 。如果 seq_len 很长,激活值仍然会成为大头。


6.4 QLoRA

QLoRA 进一步把基础模型权重量化到 4bit:

text 复制代码
基础模型权重: BF16 → INT4/NF4

但 LoRA 参数通常仍用 BF16/FP16 训练。

text 复制代码
QLoRA训练总显存 =
4bit基础模型权重
+ LoRA参数/梯度/优化器状态
+ 激活值
+ 量化反量化buffer
+ runtime开销

Qwen3-1.7B:

text 复制代码
BF16权重 ≈ 3.4GB
4bit权重 ≈ 0.85GB

所以 QLoRA 可能进一步降到:

text 复制代码
6GB ~ 10GB

但具体取决于 seq_len、batch、是否开 gradient checkpointing、视觉模型输入分辨率等。


7. Gradient Checkpointing

训练时激活值太大,可以用 gradient checkpointing。

普通训练:

text 复制代码
前向保存大部分激活值 → 反向直接用

Gradient checkpointing:

text 复制代码
前向少保存激活值 → 反向时重新计算一部分前向

优点:

text 复制代码
显存下降明显

缺点:

text 复制代码
训练速度变慢,通常慢 20% ~ 40%

它本质上是:

text 复制代码
用更多计算换更少显存

8. 预训练和微调的区别

8.1 预训练

目标: 让模型从大规模通用数据中学习语言、世界知识、视觉语言对齐能力。

数据形式通常是:

text 复制代码
海量文本
图文对
网页数据
代码数据
视频/多模态数据

训练目标通常是 next token prediction:

text 复制代码
给定前面的 token,预测下一个 token

loss 是标准交叉熵:

text 复制代码
Loss = -log P(真实下一个token | 前文)

例如文本:

text 复制代码
输入: 今天天气很
目标: 好

模型需要提高:

text 复制代码
P("好" | "今天天气很")

预训练特点:

text 复制代码
数据量极大
训练 token 数极大
通常全参数训练
成本最高
决定模型基础能力

8.2 微调 / SFT

SFT:Supervised Fine-Tuning,有监督微调。

目标不是从零学语言,而是让模型学会某种任务格式、回答风格、领域能力。

你的猫咪视觉识别数据就是典型 SFT:

json 复制代码
{
  "role": "user",
  "content": "请识别图中猫咪状态..."
}
{
  "role": "assistant",
  "content": "{\"cats_visible\": 1, ...}"
}

SFT 的 loss 通常只算 assistant 部分:

text 复制代码
user prompt 部分不算 loss
assistant answer 部分算 loss

也就是:

text 复制代码
输入: user prompt + assistant answer
Loss mask:
user prompt         → -100,不参与loss
assistant answer    → 正常token id,参与loss

交叉熵形式仍然是:

text 复制代码
Loss = -Σ log P(assistant真实token | image + prompt + 前文token)

对于你的 JSON SFT,本质是让模型学习:

text 复制代码
图像 + 指令 → 合法 JSON 结构 + 正确字段值

8.3 预训练 vs 微调

项目 预训练 微调 / SFT
目标 学基础能力 学任务格式和领域行为
数据 海量通用数据 高质量任务数据
参数 通常全参数 全参数 / LoRA / QLoRA
成本 极高 较低
loss next token loss assistant answer token loss
作用 决定模型上限 改善特定任务表现
例子 学语言、视觉知识 学会输出猫咪 JSON schema

9. 训练显存汇总对比

以 Qwen3-1.7B、BF16、seq_len=2048 为例:

方式 权重 梯度 优化器状态 激活值 总显存估计
推理 no_grad + FA2 3.4GB 0 0 0.3~0.6GB 约 6.5GB
全参数训练 3.4GB 3.4GB 13.6GB+ 4~8GB 25~38GB+
LoRA 3.4GB 很小 很小 4~8GB 8~13GB
QLoRA 约0.85GB 很小 很小 4~8GB 6~10GB

一句话总结:

text 复制代码
推理显存主要看:权重 + KV Cache
训练显存主要看:权重 + 梯度 + 优化器状态 + 激活值
全参训练贵在梯度和Adam状态
LoRA省在只训练少量参数
QLoRA进一步省在基础模型权重量化
seq_len越长,激活值越容易成为训练显存大头
相关推荐
Asize39 分钟前
146. LRU 缓存
算法
Asize42 分钟前
543. 二叉树的直径
算法
lemon_sjdk1 小时前
ObjectProperty
java·开发语言·算法
Zentceh1 小时前
AI-ISP在夜视机芯中的应用:从传统ISP到PixelClean全彩夜视的进化
人工智能·科技·算法·计算机视觉·车载系统·视频·智能硬件
xier_ran2 小时前
【infra之路】AWQ 详解:激活感知权重保护,让 W4A16 量化精度超越 GPTQ
线性代数·算法·机器学习·量化·infra
亦皓ai2 小时前
AI时代后端工程(二):AI把代码写得越来越快,我却越来越不敢让它直接开工了
人工智能·算法·机器学习·搜索引擎·transformer
玖玥拾3 小时前
LeetCode 392 判断子序列
笔记·算法·leetcode
重生之后端学习5 小时前
239. 滑动窗口最大值[困难]✅
java·数据结构·算法·leetcode·职场和发展
fpcc5 小时前
算法和数据结构—动态规划法
数据结构·算法·动态规划
星星.7227 小时前
C++算法竞赛|二分查找与二分答案:边界模板、浮点二分、STL
数据结构·c++·算法