Pytorch顺序训练多模型时无法从GPU/CPU彻底删除模型致内存溢出求解
解决方法
核心问题原因
- 你在累加损失时直接使用了张量
loss而非其数值,导致每轮迭代的计算图被持续持有,无法释放,是内存泄漏的核心诱因 - 测试阶段未关闭梯度计算,额外生成了不需要的计算图占用内存
- 仅执行
del不会立即触发Python垃圾回收,无引用的张量仍暂存在内存中 - CUDA缓存机制需要在对象被真正回收后才能释放对应的显存空间
具体修复步骤
1. 修复损失累加逻辑
将训练阶段的损失累加代码:
self.train_loss += loss
替换为:
self.train_loss += loss.item()
item()会直接提取张量的数值,不会绑定对应的计算图,避免无用计算图堆积。
2. 测试阶段关闭梯度计算
测试环节不需要反向传播,不需要保留计算图,将测试逻辑套入无梯度上下文:
with torch.no_grad(): test_error_count = 0.0 for images, labels in iter(self.test_loaderup): images = images.to(device) labels = labels.to(device) outputs = modelup(images) test_error_count += float(torch.sum(torch.abs(labels - outputs.argmax(1))))
3. 调整资源清理顺序
单组模型训练完成后的清理逻辑调整为:
# 删除所有持有模型、张量、优化器的变量 del modelup,optimizerup,test_accuracy,test_error_count,train_error_count,loss,labels,images,outputs # 手动触发Python垃圾回收,彻底释放CPU端无引用的对象 import gc gc.collect() # 清空CUDA缓存,释放GPU显存 torch.cuda.empty_cache()
不需要提前将模型转移到CPU,该顺序可以同时释放GPU和CPU的对应资源。
4. 排查额外引用
检查代码中是否存在其他持有模型/张量的隐式引用:
- 确认
self.modelforsend列表没有存储过modelup实例 - 确认发送的pyqt信号没有携带模型、张量类参数,若携带需确保槽函数使用后立即释放引用
5. 终极解决方案:使用独立进程替代线程
Python线程的资源会被主进程持有,部分场景下无法完全释放,你可以将训练逻辑改为使用multiprocessing.Process启动独立进程执行,单组训练完成后进程退出,操作系统会自动回收所有相关资源,完全避免内存泄漏问题,适合多组参数顺序训练的场景。
内容的提问来源于stack exchange,提问作者mundus131
相关产品推荐
相关产品推荐

