pytorch 运行一段时间后出现GPU OOM的问题


Posted in Python onJune 02, 2021

pytorch的dataloader会将数据传到GPU上,这个过程GPU的mem占用会逐渐增加,为了避免GPUmen被无用的数据占用,可以在每个step后用del删除一些变量,也可以使用torch.cuda.empty_cache()释放显存:

del targets, input_k, input_mask
torch.cuda.empty_cache()

这时能观察到GPU的显存一直在动态变化。

但是上述方式不是一个根本的解决方案,因为他受到峰值的影响很大。比如某个batch的数据量明显大于其他batch,可能模型处理该batch时显存会不够用,这也会导致OOM,虽然其他的batch都能顺利执行。

显存的占用跟这几个因素相关:

模型参数量

batch size

一个batch的数据 size

通常我们不希望改变模型参数量,所以只能通过动态调整batch-size,使得一个batch的数据 size不会导致显存OOM:

ilen = int(sorted_data[start][1]['input'][0]['shape'][0])
olen = int(sorted_data[start][1]['output'][0]['shape'][0])
# if ilen = 1000 and max_length_in = 800
# then b = batchsize / 2
# and max(1, .) avoids batchsize = 0
# 太长的句子会被动态改变bsz,单独成一个batch,否则padding的部分就太多了,数据量太大,OOM
factor = max(int(ilen / max_length_in), int(olen / max_length_out))
b = max(1, int(batch_size / (1 + factor)))
#b = batch_size
end = min(len(sorted_data), start + b)
minibatch.append(sorted_data[start:end])
if end == len(sorted_data):
    break
start = end

此外,如何选择一个合适的batchsize也是个很重要的问题,我们可以先对所有数据按照大小(长短)排好序(降序),不进行shuffle,按照64,32,16依次尝试bsz,如果模型在执行第一个batch的时候没出现OOM,那么以后一定也不会出现OOM(因为降序排列了数据,所以前面的batch的数据size最大)。

还有以下问题

pytorch increasing cuda memory OOM 问题

改了点model 的计算方式,然后就 OOM 了,调小了 batch_size,然后发现发现是模型每次迭代都会动态增长 CUDA MEMORY, 在排除了 python code 中的潜在内存溢出问题之后,基本可以把问题定在 pytorch 的图计算问题上了,说明每次迭代都重新生成了一张计算图,然后都保存着在,就 OOM 了。

参考

CUDA memory continuously increases when net(images) called in every iteration

Understanding graphs and state

说是会生成多个计算图:

loss = SomeLossFunction(out) + SomeLossFunction(out)

准备用 sum来避免多次生成计算图的问题:

loss = Variable(torch.sum(torch.cat([loss1, loss2], 0)))

然而,调着调着就好了,和报错前的 code 没太大差别。估计的原因是在pycharm 远程连接服务器的时候 code 的保存版本差异问题,这个也需要解决一下。

还有个多次迭代再计算梯度的问题,类似于 caffe中的iter_size,这个再仔细看看。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python实现问号表达式(?)的方法
Nov 27 Python
数据挖掘之Apriori算法详解和Python实现代码分享
Nov 07 Python
Python os模块介绍
Nov 30 Python
python通过正则查找微博@(at)用户的方法
Mar 13 Python
python下调用pytesseract识别某网站验证码的实现方法
Jun 06 Python
python读取图片并修改格式与大小的方法
Jul 24 Python
python爬虫框架scrapy实现模拟登录操作示例
Aug 02 Python
对IPython交互模式下的退出方法详解
Feb 16 Python
Python 使用matplotlib模块模拟掷骰子
Aug 08 Python
对Django的restful用法详解(自带的增删改查)
Aug 28 Python
在django中使用post方法时,需要增加csrftoken的例子
Mar 13 Python
使用Python快速打开一个百万行级别的超大Excel文件的方法
Mar 02 Python
python flask开发的简单基金查询工具
python爬取网页版QQ空间,生成各类图表
Python爬虫实战之爬取携程评论
Pytorch DataLoader shuffle验证方式
python 爬取吉首大学网站成绩单
python 批量压缩图片的脚本
Jun 02 #Python
python操作xlsx格式文件并读取
You might like
PHP配置把错误日志以邮件方式发送方法(Windows系统)
2015/06/23 PHP
PHP获取指定月份第一天和最后一天的方法
2015/07/18 PHP
php socket通信(tcp/udp)实例分析
2016/02/14 PHP
PHP实现的DES加密解密类定义与用法示例
2020/11/02 PHP
PHP实现获取毫秒时间戳的方法【使用microtime()函数】
2019/03/01 PHP
PHP时间函数使用详解
2019/03/21 PHP
IE Firefox 使用自定义标签的区别
2009/10/15 Javascript
javascript中的变量是传值还是传址的?
2010/04/19 Javascript
javascript学习笔记(五) Array 数组类型介绍
2012/06/19 Javascript
JavaScript中“过于”犀利地for/in循环使用示例
2013/10/22 Javascript
Jquery 实现table样式的设定
2015/01/28 Javascript
javascript常用的方法整理
2015/08/20 Javascript
jquery中ajax跨域方法实例分析
2015/12/18 Javascript
jQuery EasyUI中DataGird动态生成列的方法
2016/04/05 Javascript
Easyui 之 Treegrid 笔记
2016/04/29 Javascript
ECMAScript6快速入手攻略
2016/07/18 Javascript
AngulerJS学习之按需动态加载文件
2017/02/13 Javascript
Angular4.0中引入laydate.js日期插件的方法教程
2017/12/25 Javascript
详解Vue实战指南之依赖注入(provide/inject)
2018/11/13 Javascript
详解vue-element Tree树形控件填坑路
2019/03/26 Javascript
vue 路由缓存 路由嵌套 路由守卫 监听物理返回操作
2020/08/06 Javascript
Python isinstance函数介绍
2015/04/14 Python
python使用正则表达式匹配字符串开头并打印示例
2017/01/11 Python
利用python模拟sql语句对员工表格进行增删改查
2017/07/05 Python
python中装饰器级连的使用方法示例
2017/09/29 Python
Django中间件工作流程及写法实例代码
2018/02/06 Python
python进阶之多线程对同一个全局变量的处理方法
2018/11/09 Python
pyqt 实现QlineEdit 输入密码显示成圆点的方法
2019/06/24 Python
Python3和PyCharm安装与环境配置【图文教程】
2020/02/14 Python
Python接口测试环境搭建过程详解
2020/06/29 Python
2014年大学庆元旦迎新年活动方案
2014/03/09 职场文书
毕业班联欢会主持词
2014/03/27 职场文书
2014法制宣传日活动总结
2014/07/09 职场文书
小学四年级学生评语
2014/12/26 职场文书
导游词之开封禹王台风景区
2019/12/02 职场文书
golang中的并发和并行
2021/05/08 Golang