报错是这么冒出来的。7B 模型微调,开 gradient_checkpointing 之后 80GB 卡上 batch size 只能给 2,不开反而能到 3。脚本用 transformers 4.44 加 deepspeed zero2,每步耗时从 1.8 秒涨到 2.9 秒,显存峰值出现在重算阶段。把 max_length 从 4096 调到 3072 也没改善。
中间走过弯路,把「zero2 的分片在重算时需要 all-gather,额外占一份显存」当成主因,改完现象没变。
排查方向其实有限,先把可能性排一排。重算阶段要重新保存输入激活,临时峰值超过普通前向。还有一种是序列 4096 时重算产生的中间张量比省下来的还多。
另外,use_reentrant 默认是 True,保留的输入比手写实现更多。
动手时先对比开启前后的峰值显存
python -c "import torch;print(torch.cuda.max_memory_allocated()/2**30)"
随后换成非重入实现减少保留张量
python -c "print('gradient_checkpointing_kwargs={use_reentrant: False}')"
再往下把序列长度降到 2048 再测 batch 上限
python -c "print('max_length 4096 -> 2048')"
末了记录每步耗时确认没有明显回退
python -c "print('step time 1.8s -> 1.9s')"
怎么算真的好了,看的是同一批现象。换成非重入版检查点后 batch size 回到 3,峰值显存低于不开启时的九成,每步耗时增加不到 8%。
提醒一点。检查点不是免费省显存,重算阶段有临时峰值,序列一长就要先算这笔账再决定开不开。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
