pytorch显存持续上涨主因是gpu张量被意外引用未释放:梯度未清空、计算图存入容器、推理未用no_grad、empty_cache调用时机错误;应优先排查引用源并用memory_summary定位泄漏点。

torch.cuda.memory_allocated() 持续上涨,不是显存“没释放”,而是你代码里有东西正牢牢拽着 GPU 张量不放——PyTorch 不会主动杀掉还被引用的对象,哪怕它早该被扔了。
图片提示词生成器?不止如此。 马甲系统 —— 把脑海中的画面,翻译成AI能理解的专业表达。 用得越多,它越懂你:首次需要多问几句确认方向,用久了几乎一说就懂。 用得越多,它越快:缓存机制让后续对话越来越省。 RAG进化:成功案例持续入库,越跑越聪明。 输入「新手指南」查看完整功能介绍
梯度没清空,grad 就是显存钉子
loss.backward() 后不调 optimizer.zero_grad(),梯度就一直累积在 param.grad 里。更隐蔽的是:手动清 grad 时只写了 param.grad = None,但忘了遍历所有参数;或者用了 model.zero_grad() 却没确认 model 是否包含全部可训练参数(比如自定义 head 没注册进 nn.Module)。
-
optimizer.zero_grad()是最稳妥的选择,它按 optimizer 管理的参数列表操作 - 如果用 DDP,确保
zero_grad()在backward()之后、step()之前 - 检查
model.named_parameters()中是否有requires_grad=True但没被 optimizer 覆盖的参数
计算图被意外存进 list 或 dict
把带requires_grad=True 的张量直接 .append() 进 Python 容器,等于把整条前向路径上的所有中间变量都锁死在显存里。
- 错误写法:
losses.append(loss)(loss是标量 tensor,但带完整图) - 正确写法:
losses.append(loss.item())或losses.append(loss.detach().cpu().item()) - 推理阶段务必包
with torch.no_grad():,否则model(x)生成的每个中间输出都在图里 - 即使用了
.detach(),如果后续又把它塞进列表,仍会保留对原始 storage 的引用
torch.cuda.empty_cache() 为什么总像没用?
它只回收“没人要的缓存块”,不是 GC。只要还有 Python 变量指着某块显存,empty_cache() 就绕不开。
- 典型无效场景:循环里每步都
output = model(x); del output; torch.cuda.empty_cache()——但output被上一轮的history列表还留着引用 - 正确顺序:先
del所有可能引用,再torch.cuda.empty_cache() - 高频调用反而拖慢速度:它会清空分配器缓存,下次小张量分配得重新向 CUDA driver 申请页
验证泄漏点最直接的办法
别猜,用torch.cuda.memory_summary() 对比快照:
- 在循环前后各调一次:
torch.cuda.memory_summary(abbreviated=False) - 关注输出里重复出现的 stack trace,尤其含
forward、collate_fn、<strong>call</strong>的行 - 如果看到大量 allocation 没有对应释放,且 trace 都指向你写的某个函数,基本就是那儿漏了
真正难处理的从来不是“怎么清”,而是“谁还在引用”。一个没被 del 的临时变量、一个忘记 .item() 的 loss、甚至一个自定义 hook 里缓存的 tensor,都可能让显存缓慢爬升到崩溃边缘。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










