问题出现得很突然,日志倒是留得挺全。八卡 A100 训练 7B 模型,第二个 epoch 偶发 CUDA out of memory,报错里 allocated 六十二 GB、reserved 七十 GB,但训练日志按 epoch 打一行汇总,看不出峰值出现在第几步;torch 2.4,脚本用 accelerate 起多卡。
刚开始盯着「OOM 发生在反传阶段,异常被上层捕获后丢了步号」,折腾了半个多小时,排掉了。
排查方向其实有限,先把可能性排一排。只在异常处打印显存,没有按步记录峰值。还有一种是分配量与保留量混在一行,看不出碎片有多少。
另外,分布式训练只打了 rank0 的显存,其他卡是黑的。
每步打印分配峰值与保留峰值
python -c "import torch;print(torch.cuda.max_memory_allocated()/2**30, torch.cuda.max_memory_reserved()/2**30)"
然后在训练循环里按步重置峰值统计
python train.py --log-mem-every 10 --reset-peak
OOM 时把显存快照落盘留证
python -c "import torch;torch.cuda.memory._dump_snapshot('oom.pickle')"
剩下的就是打一份分段汇总确认占用来自哪里
python -c "import torch;print(torch.cuda.memory_summary(device=0, abbreviated=True))"
改完先别撤,确认这几项。日志里能看到 OOM 前一步的分配与保留峰值,汇总显示大块来自激活值而不是权重,缩小 batch 后不再复现。
补一句。显存峰值只在一瞬间出现,事后看监控已经晚了,按步记录峰值是定位 OOM 最省事的办法。线上能稳定复现的问题都不算难,难的是只在大流量下才出现的那种。
