torch.cuda.empty_cache() 仅释放未被张量引用的缓存显存,不回收仍被变量或模型持有的显存;需配合 del、zero_grad() 和 no_grad() 才能有效释放。

torch.cuda.empty_cache() 为什么经常没用
它只释放“缓存中未被张量引用的显存”,不是 GC,也不管 Python 对象是否还活着。如果你有 torch.Tensor 还在变量里挂着(哪怕只是临时变量没 del),或者模型还在 nn.Module 里绑着,empty_cache() 就清不掉那块显存。
常见错误现象:nvidia-smi 显示显存占用越来越高,但调了多次 torch.cuda.empty_cache() 后几乎没变化。
- 检查是否有未释放的中间变量:比如训练循环里反复做
output = model(x)却没把output显式del或覆盖 - 验证是否启用了梯度:
with torch.no_grad():外层没包住推理逻辑,导致计算图残留 - 注意
model.eval()不等于释放显存——它只关 dropout/bn,不影响已分配的参数或缓存
真正能释放显存的三步操作
单靠 empty_cache() 是治标;得配合 Python 的引用管理和 PyTorch 的生命周期控制。
- 手动切断张量引用:
del output, loss, logits—— 尤其在 eval 或多轮 inference 场景下,别依赖自动回收 - 清空计算图:
loss.backward()后立刻optimizer.zero_grad(),否则grad引用会拖住整张图 - 最后才调
torch.cuda.empty_cache():放在所有del和zero_grad()之后,且建议只在 debug 或 batch 间歇时用,别塞进每步 forward
示例片段:
立即学习“Python免费学习笔记(深入)”;
for x, y in dataloader:
with torch.no_grad():
pred = model(x)
# ... 计算指标
del pred # 关键:主动删掉输出张量
torch.cuda.empty_cache() # 放在这里才可能生效哪些情况 empty_cache() 反而有害
它会强制清空 CUDA 缓存分配器里的空闲块,导致后续小张量分配变慢(重新向 driver 申请页)。高频调用不仅无效,还拖慢速度。
- 不要在每个
forward()后加empty_cache() - 避免在多卡训练中误用:它只作用于当前
current_device,若用torch.cuda.set_device(1)切过卡,要确保 cache 清的是目标卡 - 和
torch.cuda.memory_summary()搭配看更准:运行一次后查allocated和reserved差值,比nvidia-smi更反映真实使用
排查泄漏的最小可行路径
别一上来就改代码,先确认是不是真泄漏、漏在哪。
- 加监控:在关键点插入
print(torch.cuda.memory_allocated()/1024**3),看增长趋势 - 禁用缓存分配器测试:
os.environ['PYTORCH_CUDA_ALLOC_CONF'] = 'max_split_size_mb:128'(防止大块内存被长期 hold) - 怀疑模型层泄漏?试试
model.cpu(); del model后再empty_cache(),看显存是否回落
最常被忽略的是:DataLoader 的 pin_memory=True + GPU tensor 预加载,会在 worker 进程里悄悄占显存,且不归主进程 empty_cache() 管。


















