显存溢出主因是CUDA缓存碎片而非物理显存不足,需结合变量清理、模式切换与结构检查缓解;memory_allocated()跳变因不统计缓存碎片,应使用memory_summary()诊断。

显存溢出不是GPU真没内存了,而是 PyTorch 的缓存分配器找不到连续大块显存——torch.cuda.empty_cache() 单独调用基本无效,必须配合变量清理、模式切换和结构检查才能真正缓解。
为什么 memory_allocated() 突然跳变还报 OOM?
这是 CUDA 缓存机制的典型表现:torch.cuda.memory_allocated() 只统计当前活跃张量占用,不包含缓存碎片。当你需要分配一个 512MB 张量时,即使 free 显示有 6GB,若缓存里全是 4MB/8MB 的碎块,就无法拼出连续空间,直接触发 RuntimeError: CUDA out of memory。
- 别只看
memory_allocated(),改用torch.cuda.memory_summary()查碎片和cached量 - 错误信息里带
XX MiB cached就说明是缓存问题,不是物理显存耗尽 - 反复创建不同尺寸张量(比如在 for 循环里随机 shape)极易加剧碎片,尤其在调试阶段
batch_size=1 还 OOM?重点查这三处隐性开销
BatchNorm 层、优化器状态、残留引用才是小 batch 下的真凶。
-
nn.BatchNorm2d在model.train()模式下会为每个 channel 分配临时缓冲区,高分辨率输入(如 2448×2448)时单层就能吃掉几百 MB,跟batch_size无关 -
AdamW比SGD多占约 2 倍显存(动量 + 二阶矩),临时换torch.optim.SGD能快速验证是否是优化器拖累 - 全局列表、日志对象、闭包里意外保留了
output或loss引用,导致张量无法被回收;用del output; torch.cuda.empty_cache()后再检查memory_allocated()是否回落
训练中该在哪删变量、何时清缓存?
不是每步都清,也不是等报错才清。关键节点只有三个:
调用 Cutout.Pro 视觉处理 API 进行背景移除、人像抠图和照片增强,支持文件上传与图片 URL 输入。
立即学习“Python免费学习笔记(深入)”;
-
optimizer.step()后立刻del loss, outputs, logits,再调torch.cuda.empty_cache() - 验证前加
with torch.no_grad():,且确保model.eval()已调用(BN 不更新、不存 running stats) - 每个 epoch 结束时清一次,避免跨 epoch 碎片累积;别在 dataloader 循环内频繁调用,它有毫秒级延迟
loss.backward() 才爆显存?大概率是计算图撑爆
前向没问题、反向挂掉,说明中间激活值或梯度图没释放。常见于自定义 loss、RNN 展开、torch.cat() 拼接大量输出。
- 在
loss.backward()前插torch.cuda.memory_snapshot()(PyTorch 1.10+),用torch.cuda._memory_viz.trace_plot()定位哪一层张量最大 - 避免
total_loss += loss,改用total_loss = total_loss + loss并适时.item()提取标量 - 长序列任务启用梯度检查点:
torch.utils.checkpoint.checkpoint(model, x),显存可降 30%–50%,但训练时间增加
最常被忽略的是:nn.DataParallel 套在单卡模型上会复制整个模型到多个 device,显存直接 ×N;还有混合精度中,autocast 区域外漏了 torch.tensor(..., dtype=torch.float32),会让 float32 张量悄悄破坏内存节省效果。

















