pytorch显存一直变大的解决方案


Posted in Python onApril 08, 2021

在代码中添加以下两行可以解决:

torch.backends.cudnn.enabled = True
torch.backends.cudnn.benchmark = True

补充:pytorch训练过程显存一直增加的问题

之前遇到了爆显存的问题,卡了很久,试了很多方法,总算解决了。

总结下自己试过的几种方法:

**1. 使用torch.cuda.empty_cache()

在每一个训练epoch后都添加这一行代码,可以让训练从较低显存的地方开始,但并不适用爆显存的问题,随着epoch的增加,最大显存占用仍然会提示out of memory 。

2.使用torch.backends.cudnn.enabled = True 和 torch.backends.cudnn.benchmark = True

原理不太清楚,用法和1一样。但是几乎没有效果,直接pass。

3.最重要的:查看自己的forward函数是否存在泄露。

常需要在forward函数里调用其他子函数,这时候要特别注意:

input尽量不要写在for循环里面!!!

子函数里如果有append()等函数,一定少用,能不用就不用!!!

子函数list一定少用,能不用就不用!!!

总之,子函数一般也不会太复杂,直接写出来,别各种for,嵌套,变量。!!!

补充:Pytorch显存不断增长问题的解决思路

这个问题,我先后遇到过两次,每次都异常艰辛的解决了。

在网上,关于这个问题,你可以找到各种看似不同的解决方案,但是都没能解决我的问题。所以只能自己摸索,在摸索的过程中,有了一个排查问题点的思路。

下面举个例子说一下我的思路。

大体思路

其实思路很简单,就是在代码的运行阶段输出显存占用量,观察在哪一块存在显存剧烈增加或者显存异常变化的情况。

但是在这个过程中要分级确认问题点,也即如果存在三个文件main.py、train.py、model.py。

在此种思路下,应该先在main.py中确定问题点,然后,从main.py中进入到train.py中,再次输出显存占用量,确定问题点在哪。

随后,再从train.py中的问题点,进入到model.py中,再次确认。

如果还有更深层次的调用,可以继续追溯下去。

具体例子

main.py

def train(model,epochs,data):
    for e in range(epochs):
        print("1:{}".format(torch.cuda.memory_allocated(0)))
        train_epoch(model,data)
        print("2:{}".format(torch.cuda.memory_allocated(0)))
        eval(model,data)
        print("3:{}".format(torch.cuda.memory_allocated(0)))

假设1与2之间显存增加极为剧烈,说明问题出在train_epoch中,进一步进入到train.py中。

train.py

def train_epoch(model,data):
    model.train()
    optim=torch.optimizer()
    for batch_data in data:
        print("1:{}".format(torch.cuda.memory_allocated(0)))
        output=model(batch_data)
        print("2:{}".format(torch.cuda.memory_allocated(0)))
        loss=loss(output,data.target)
        print("3:{}".format(torch.cuda.memory_allocated(0)))
        optim.zero_grad()
        print("4:{}".format(torch.cuda.memory_allocated(0)))
        loss.backward()
        print("5:{}".format(torch.cuda.memory_allocated(0)))
        utils.func(model)
        print("6:{}".format(torch.cuda.memory_allocated(0)))

如果在1,2之间,5,6之间同时出现显存增加异常的情况。此时需要使用控制变量法,例如我们先让5,6之间的代码失效,然后运行,观察是否仍然存在显存爆炸。如果没有,说明问题就出在5,6之间下一级的代码中。进入到下一级代码,进行调试:

utils.py

def func(model):
print("1:{}".format(torch.cuda.memory_allocated(0)))
a=f1(model)
print("2:{}".format(torch.cuda.memory_allocated(0)))
b=f2(a)
print("3:{}".format(torch.cuda.memory_allocated(0)))
c=f3(b)
print("4:{}".format(torch.cuda.memory_allocated(0)))
d=f4(c)
print("5:{}".format(torch.cuda.memory_allocated(0)))

此时我们再展示另一种调试思路,先注释第5行之后的代码,观察显存是否存在先训爆炸,如果没有,则注释掉第7行之后的,直至确定哪一行的代码出现导致了显存爆炸。假设第9行起作用后,代码出现显存爆炸,说明问题出在第九行,显存爆炸的问题锁定。

几种导致显存爆炸的情况

pytorch的hook机制可能导致,显存爆炸,hook函数取出某一层的输入输出跟权重后,不可进行存储,修改等操作,这会造成hook不能回收,进而导致取出的输入输出权重都可能不被pytorch回收,所以模型的负担越来也大,最终导致显存爆炸。

这种情况是我第二次遇到显存爆炸查出来的,非常让人匪夷所思。在如下代码中,p.sub_(torch.mm(k, torch.t(k)) / (alpha + torch.mm(r, k))),导致了显存爆炸,这个问题点就是通过上面的方法确定的。

这个P是一个矩阵,在使用p.sub_的方式更新P的时候,导致了显存爆炸。

将这行代码修改为p=p-(torch.mm(k, torch.t(k)) / (alpha + torch.mm(r, k))),显存爆炸的问题解决。

def pro_weight(p, x, w, alpha=1.0, cnn=True, stride=1):
                if cnn:
                    _, _, H, W = x.shape
                    F, _, HH, WW = w.shape
                    S = stride  # stride
                    Ho = int(1 + (H - HH) / S)
                    Wo = int(1 + (W - WW) / S)
                    for i in range(Ho):
                        for j in range(Wo):
                            # N*C*HH*WW, C*HH*WW = N*C*HH*WW, sum -> N*1
                            r = x[:, :, i * S: i * S + HH, j * S: j * S + WW].contiguous().view(1, -1)
                            # r = r[:, range(r.shape[1] - 1, -1, -1)]
                            k = torch.mm(p, torch.t(r))
                            p.sub_(torch.mm(k, torch.t(k)) / (alpha + torch.mm(r, k)))
                    w.grad.data = torch.mm(w.grad.data.view(F, -1), torch.t(p.data)).view_as(w)
                else:
                    r = x
                    k = torch.mm(p, torch.t(r))
                    p.sub_(torch.mm(k, torch.t(k)) / (alpha + torch.mm(r, k)))
                    w.grad.data = torch.mm(w.grad.data, torch.t(p.data))

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。如有错误或未考虑完全的地方,望不吝赐教。

Python 相关文章推荐
使用Python中的greenlet包实现并发编程的入门教程
Apr 16 Python
Python面向对象编程中关于类和方法的学习笔记
Jun 30 Python
详解Python list 与 NumPy.ndarry 切片之间的对比
Jul 24 Python
使用python实现ANN
Dec 20 Python
Numpy中的mask的使用
Jul 21 Python
Python multiprocess pool模块报错pickling error问题解决方法分析
Mar 20 Python
pytorch 获取层权重,对特定层注入hook, 提取中间层输出的方法
Aug 17 Python
pytorch使用 to 进行类型转换方式
Jan 08 Python
django实现模板中的字符串文字和自动转义
Mar 31 Python
python进行参数传递的方法
May 12 Python
使用tensorflow根据输入更改tensor shape
Jun 23 Python
python自动化测试之Selenium详解
Mar 13 Python
Python文件的操作示例的详细讲解
Django展示可视化图表的多种方式
python tkinter模块的简单使用
python如何在word中存储本地图片
python 下载文件的几种方式分享
Apr 07 #Python
完美处理python与anaconda环境变量的冲突问题
python 如何用map()函数创建多线程任务
You might like
PHP异步调用socket实现代码
2012/01/12 PHP
PHP获取服务器端信息的方法
2014/11/28 PHP
ThinkPHP添加更新标签的方法
2014/12/05 PHP
php文件操作之小型留言本实例
2015/06/20 PHP
php文件上传的两种实现方法
2016/04/04 PHP
thinkPHP显示不出验证码的原因与解决方法分析
2017/05/20 PHP
让网页根据不同IE版本显示不同的内容
2009/02/08 Javascript
Mootools 1.2教程 滚动条(Slider)
2009/09/15 Javascript
javascript中常用编程知识
2013/04/08 Javascript
浅析showModalDialog数据缓存问题(用禁止浏览器缓存解决)
2013/07/09 Javascript
js操作iframe兼容各种主流浏览器示例代码
2013/07/22 Javascript
Bootstrap 组件之按钮(二)
2016/05/11 Javascript
DOM操作和jQuery实现选项移动操作的简单实例
2016/06/07 Javascript
Chrome不支持showModalDialog模态对话框和无法返回returnValue问题的解决方法
2016/10/30 Javascript
Angular2环境搭建具体操作步骤(推荐)
2017/08/04 Javascript
vue router嵌套路由在history模式下刷新无法渲染页面问题的解决方法
2018/01/25 Javascript
nodejs实现连接mongodb数据库的方法示例
2018/03/15 NodeJs
Vue前端开发规范整理(推荐)
2018/04/23 Javascript
修改npm全局安装模式的路径方法
2018/05/15 Javascript
vue生命周期和react生命周期对比【推荐】
2018/09/19 Javascript
解决 viewer.js 动态更新图片导致无法预览的问题
2019/05/14 Javascript
[31:01]2014 DOTA2国际邀请赛中国区预选赛5.21 CNB VS Orenda
2014/05/23 DOTA
[47:48]DOTA2上海特级锦标赛D组小组赛#2 Liquid VS VP第三局
2016/02/28 DOTA
Python3中条件控制、循环与函数的简易教程
2017/11/21 Python
Python爬虫实例_城市公交网络站点数据的爬取方法
2018/01/10 Python
Python使用pyodbc访问数据库操作方法详解
2018/07/05 Python
python json 递归打印所有json子节点信息的例子
2020/02/27 Python
Python 3.8 新功能来一波(大部分人都不知道)
2020/03/11 Python
公司总经理岗位职责
2014/03/15 职场文书
培训讲师岗位职责
2014/04/13 职场文书
机关领导查摆四风思想汇报
2014/09/13 职场文书
部门群众路线教育实践活动对照检查材料思想汇报
2014/10/07 职场文书
我们的节日端午节活动总结
2015/02/11 职场文书
大学生个人学年总结
2015/02/15 职场文书
酒店前台接待岗位职责
2015/04/02 职场文书
linux下导入、导出mysql数据库命令的实现方法
2021/05/26 MySQL