You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

深度神经网络训练突发OOM:loss张量保留引发内存泄漏问题咨询

问题解答

1. 是否可以手动删除loss张量后继续训练

可以,但是要注意操作细节:

  • 正常情况下PyTorch调用backward()且没有设置retain_graph=True时,对应的计算图会自动释放,不需要手动删除loss张量。但如果存在其他引用持有了loss张量(比如全局日志列表存储了CUDA侧的loss张量),手动删除可以释放对应显存。
  • 删除操作需要覆盖所有中间loss变量,不止最终的loss_gen_all:在scaler.update()执行完成后新增如下代码即可:
del loss_dur, loss_mel, loss_kl, loss_fm, loss_gen, losses_gen, loss_gen_all
torch.cuda.empty_cache()
  • 注意不要每步都调用torch.cuda.empty_cache(),会显著降低训练速度,建议每100~500步调用一次即可。

2. 如何验证是否存在loss张量持续存储的问题

可以通过以下几个可落地的方法排查:

  • 首先监控迭代级的显存变化:每轮迭代结束后打印torch.cuda.memory_allocated()的返回值,如果数值随迭代次数稳定上涨(每次涨几十KB到几MB不等),就可以确定存在显存泄漏。
  • 统计CUDA侧loss类张量的数量:在每轮迭代结束、清理完缓存后运行以下代码,观察计数是否随迭代持续增加:
import gc
gc.collect()
torch.cuda.empty_cache()
loss_tensor_count = 0
for obj in gc.get_objects():
    try:
        if torch.is_tensor(obj) and obj.is_cuda and 'loss' in str(type(obj)):
            loss_tensor_count += 1
    except:
        pass
print(f"当前CUDA上留存的loss类张量数量:{loss_tensor_count}")
  • 排查全局loss存储逻辑:90%以上的这类问题都是因为记录loss时直接把CUDA侧的张量存入了全局列表,正确的写法是用.item()转成Python原生标量再存储,比如loss_log.append(loss_gen_all.item())而非loss_log.append(loss_gen_all)。同理检查判别器侧的loss存储逻辑,避免出现同样的问题。

3. 是否可以回退一个epoch并停止存储loss张量

如果有上一个epoch的完整checkpoint(包含模型权重、优化器状态、scaler状态),可以直接加载该checkpoint重新训练,修复loss存储的逻辑后就不会再出现持续泄漏的问题。
如果没有保存上一个epoch的checkpoint,无法直接回退,可以先执行手动删除loss张量、清理显存的操作,尽可能复用当前训练状态继续训练,建议后续训练时调高checkpoint的保存频率,避免意外丢失训练进度。

另外补充你提到的.detach()放置问题:你当前的代码里计算loss用到的fmap_r是判别器对真实样本的输出,不需要参与生成器的梯度计算,建议在拿到fmap_r后立即执行fmap_r = [x.detach() for x in fmap_r],可以避免不必要的计算图留存,也能减少显存占用。


内容的提问来源于stack exchange,提问作者John G.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 15:54:07