PyTorch 2.4 训练一个多任务模型,前 200 步显存平稳在 18GB,之后每步涨 200MB 左右直到 OOM,batch 不变、数据不变,重启后仍从第 200 步开始涨。
一开始怀疑是「日志里存了带梯度的 tensor 引用」,查了一圈,方向不对。
这类报错背后常见的原因有几处,逐个排除就行。多任务损失反传时 retain_graph 开着,计算图没释放。少数情况下是验证阶段没有 torch.no_grad,图被挂到全局列表。
少数情况下是自定义层缓存了中间激活没有 detach。
第一件事是打印每步的显存分配与保留量
python -c "import torch;print(torch.cuda.memory_allocated()/2**20, torch.cuda.memory_reserved()/2**20)"
随后确认反传参数里 retain_graph 的取值
grep -rn 'retain_graph' train.py
接着验证循环包上 no_grad 并 detach 日志张量
python -c "import torch;print(torch.is_grad_enabled())"
剩下的就是用内存快照定位持续增长的分配点
python -c "import torch;torch.cuda.memory._record_memory_history();print('on')"
别只看报错消失,验证要多做一步。连续跑 500 步显存曲线保持水平,allocated 与 reserved 的差值稳定,不再出现阶梯式上涨。
这里还有个坑。阶梯式增长基本都是引用没断,跟 batch 大小无关,先用显存快照找到持有者,再决定是 detach 还是关图。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
