torch.cuda.empty_cache()只清空未被引用的缓存块,对仍被张量引用的显存无效;常见失效场景包括del后引用计数未归零、漏用torch.no_grad()、batchnorm累积统计量、输出结构未完全释放及torch.compile()顽固缓存。

torch.cuda.empty_cache() 为什么没反应?
它根本不是“清显存”,而是“清缓存池里没人用的空闲块”。只要还有任意一个 Tensor 持有对某块显存的引用,torch.cuda.empty_cache() 就完全无视那块内存——哪怕你刚写了 del x,只要 Python 引用计数还没降到 0(比如被闭包、日志列表、全局变量或 model.named_buffers() 中的 running_mean 暗中持有),它就动不了。
哪些情况调了也白调?
常见无效场景包括:
-
del outputs后立刻调用torch.cuda.empty_cache():Python 垃圾回收还没跑,引用还在 - 验证阶段漏了
with torch.no_grad():,导致loss.backward()残留计算图,中间激活值持续被引用 - BatchNorm 层处于
train()模式,running_mean和running_var在每个 batch 后自动累积,显存越跑越多 - 输出是
dict或tuple,只del pred但没删pred['logits']或pred[0],引用链依然完整 - 用了
torch.compile(),首次运行后缓存更顽固,empty_cache()对已编译图的内部缓存基本无效
怎么确认它到底有没有起作用?
别信 nvidia-smi,它只显示驱动层总占用。真正要看的是 PyTorch 自己的内存视图:
在调用前后加这两行:
print(f"Allocated: {torch.cuda.memory_allocated()/1024**3:.2f} GB")<br>print(f"Reserved: {torch.cuda.memory_reserved()/1024**3:.2f} GB")
如果
Allocated 没变、Reserved 下降了,说明它确实清了缓存池;如果两个都没变,问题一定出在活跃引用上。
真正该做的三件事,比狂调 empty_cache() 有用得多
显存卡死时,优先检查:
- 所有中间变量是否在不用后立即
del,尤其loss、outputs、logits,且确保不在任何容器里偷偷存了一份 - 验证/推理逻辑是否全部包裹在
with torch.no_grad():内——连预处理里的torch.tensor(...).cuda()都要包进去 - 用
torch.cuda.memory_summary()查active和inactive分布,重点盯allocated_bytes.all.current和reserved_bytes.all.current的差值,这才是真实碎片量
缓存清理只是收尾动作,不是救命稻草。真正吃显存的,永远是活着的张量,不是躺在缓存池里等回收的“尸体”。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











