Python跑循环时内存泄露的解决方法


Posted in Python onJanuary 13, 2020

Python跑循环时内存泄露

今天在用Tensorflow跑回归做测试时,仅仅需要循环四千多次 (补充说一句,我在个人PC上跑的)。运行以后,我就吃饭去了。等我回来后,Console窗口直接亮红了!!!

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import tensorflow as tf
import matplotlib.font_manager as fm
myfont = fm.FontProperties(fname='C:/Windows/Fonts/simsun.ttc')
sess = tf.Session()

for j in range(0,4096):
  print('第' + str(j) + '次回归')
  ......

此处忘了截图,反正就是说Keras出现了什么什么错误。然后我就顺手重启了工程。

接着就瞪着屏幕,为什么跑一半出错了???

Python跑循环时内存泄露的解决方法

这个时候我发现电脑管家的小火箭好像有点‘暴躁',打开任务管理器一看,果然。。。

Python跑循环时内存泄露的解决方法

Python占用内存都快两个G了,但是平时跑没有占用这么多呀。我就猜想是不是因为跑循环,内存没有释放,导致最后溢出,然后code就崩了。

抱着猜想的心态等了一分钟,然后。。

Python跑循环时内存泄露的解决方法

WTF 飙到两千三百多兆的占用了。结论很明显了,就是没有释放内存!!!
这让我想起来一个月前我在集群上并行GPU跑LSTM时,出现了Out of memory,

Python跑循环时内存泄露的解决方法

这是2080ti呀,足足十一个G的内存,虽然当时我就用了一块显卡,但也不至于溢出吧。当时没有想到是这个问题,现在回想一下十有八九就是没有释放内存。

至于为什么没有释放内存,那就要从下面这个人出生的时候说起了—>

Python跑循环时内存泄露的解决方法

还记得那是一个月黑风高夜晚,天空电闪雷鸣。。。。。。
hhh,开个玩笑,这个人是Python之父,不过我觉得接下来我要说的Python垃圾收集机制或多或少和他有一定的关系。

Python垃圾收集机制

现在的高级语言如java,c#等,都采用了垃圾收集机制,而不再是c,c++里用户自己管理维护内存的方式。自己管理内存极其自由,可以任意申请内存,但如同一把双刃剑,为大量内存泄露,悬空指针等bug埋下隐患。

对于一个字符串、列表、类甚至数值都是对象,且定位简单易用的语言,自然不会让用户去处理如何分配回收内存的问题。

python里也同java一样采用了垃圾收集机制,不过不一样的是:

python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略。

Python中的内存管理过程非常简单。Python通过保持对每个对象在程序中的引用计数来处理其对象,这意味着每个对象存储在程序中被引用的次数。此计数随程序运行时更新,并且当计数为零时,这意味着程序不再可访问该计数。因此,解释器可以回收和释放该对象的内存。

class User(object):
  def __del__(self):
    print("No reference left for {}".format(self))
user1 = User()
user2 = user1
user3 = user1

在此示例中,我们制作了一个类和3个引用变量指向同一对象。让我们将其可视化:

Python跑循环时内存泄露的解决方法

现在,让变量user1,user2和user3指向None而不是User实例。

>>> user1 = None
>>> user2 = None
>>> user3 = None
No reference left for <__main__.User object at 0x212bee9d9>

通过以上代码,引用已更改为:

Python跑循环时内存泄露的解决方法

将最后一个变量分配user3给后None,该对象将被垃圾回收,这将调用该__del__函数。
从根本上讲,每当引用对象时,Python对象的引用计数都会增加,而在取消引用对象时,Python的引用计数会减少。如果对象的引用计数为0,则将释放该对象的内存。您程序的代码无法禁用Python的引用计数。

python跑循环为什么没有释放内存

有些人认为,引用计数是A poor man's garbage collector 。很大一部分原因是它存在一些缺点,其中就包括无法检测到循环应用。
如果在循环引用中的对象定义了__del__函数,那么在循环引用中Python解释器无法判断析构对象的顺序,因此就不做处理,python gc不能进行回收。

解决办法

在提出解决问题之前,我们要先找到问题。因为我这个Code需要画图,然后保存到本地。我就想是不是画的图导致占用过多内存。

F_max = max(y_result)
plt.figure(figsize=(15, 5)) 
plt.subplot(131)
plt.scatter(Yp_data, Yt_data, alpha=0.8)
plt.title(u'回归前结果',fontproperties=myfont)
plt.plot([0,F_max], [0,F_max], color = 'r')
  
plt.subplot(132)
plt.scatter(y_result, Yt_data, alpha=0.8)
plt.title(u'回归后结果',fontproperties=myfont)
plt.plot([0,F_max], [0,F_max], color = 'r')
  
plt.subplot(133)
plt.plot(loss_vec, 'k-')
plt.title('loss per Generation')
plt.xlabel('Generation')
plt.ylabel('Loss')
plt.savefig('D:/lwt/py/Regression/figure/{} .png'.format(_type), dpi=100)
plt.show()

有想法你就要去做是吧,然后我就加了两行代码。

plt.close('all')
plt.clf()

这两句是用来清除内存中的图像和清理掉 axes,并且为了尽可能的减少内存占用,把plt.show()都删除了
然后运行Code,打开任务管理器,测试是否管用。
貌似python占用的内存是没有之前上升的那么快了,不知道是不是心理作用hh。反正效果不明显,看来得从别的地方下手了。
排除掉这个可能,那就是回收机制的锅了。既然你不主动,那我就主动点咯(猿式阴笑嘿嘿)。

for x in list(locals().keys())[:]:
  del locals()[x]
gc.collect()

for循环就不要过多解释了,先说del 语句的用法

del obj_name

del是一个Python关键字。而且,obj_name 可以是变量,用户定义的对象,列表,列表中的项,字典等。可以用来删除用户定义的对象;删除变量,列表和字典;从列表中删除项目和切片;从字典中删除键等等。具体用法大家可以查找相关文档了解。

gc是python的垃圾回收器接口,gc.collect(generation=2)若被调用时不包含参数,则启动完全的垃圾回收。可选的参数 generation 可以是一个整数,指明需要回收哪一代(从 0 到 2 )的垃圾。当参数 generation 无效时,会引发 ValueError 异常。返回发现的不可达对象的数目。每当运行完整收集或最高代 (2) 收集时,为多个内置类型所维护的空闲列表会被清空。 由于特定类型特别是 float 的实现,在某些空闲列表中并非所有项都会被释放。

实测,有明显的效果,内存占用上升的速度明显减小了,不过总体还是承上升的趋势。相比之前,好太多了有没有。
方法总比困难多,解决内存泄漏也还有其他的办法。我们还可以用objgraph、weakref等工具来分析并解决内存泄露、循环引用问题。实在不行,还有一个超级硬核的办法,自己动手写一个腾讯电脑管家小火箭的脚本,时不时的让它上上天(腾讯记得打钱啊啊啊)。哈哈哈

在任何环境,不管是服务器,客户端,内存泄露都是非常严重的事情。如果是线上服务器,那么一定得有监控,如果发现内存使用率超过设置的阈值则立即报警,尽早发现些许还有救。

新的问题

不要强行收集垃圾太多次。这是因为,即使要释放内存,仍然需要花费时间来评估对象是否符合垃圾收集条件。我在实测中的确发现运行速度有些下降。
还有就是他会把全局的变量都删了,以至于出现nppd等导入的包都not defined。我的建议是把循环写到函数里,做到只对某个函数起作用。

笔者作为一个学生也是刚接触python不久,如有不对的地方还请指正,谢谢~

 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
easy_install python包安装管理工具介绍
Feb 10 Python
将Django框架和遗留的Web应用集成的方法
Jul 24 Python
python中利用xml.dom模块解析xml的方法教程
May 24 Python
Python工程师面试必备25条知识点
Jan 17 Python
python opencv之分水岭算法示例
Feb 24 Python
Python3.7中安装openCV库的方法
Jul 11 Python
在Python运行时动态查看进程内部信息的方法
Feb 22 Python
Python单元和文档测试实例详解
Apr 11 Python
python tkinter实现彩球碰撞屏保
Jul 30 Python
详解pycharm连接不上mysql数据库的解决办法
Jan 10 Python
python实现飞船大战
Apr 24 Python
Python 字典中的所有方法及用法
Jun 10 Python
PyTorch使用cpu加载模型运算方式
Jan 13 #Python
Python如何读取文件中图片格式
Jan 13 #Python
详解python破解zip文件密码的方法
Jan 13 #Python
PyTorch 随机数生成占用 CPU 过高的解决方法
Jan 13 #Python
python批量处理txt文件的实例代码
Jan 13 #Python
Python hashlib常见摘要算法详解
Jan 13 #Python
Pytorch释放显存占用方式
Jan 13 #Python
You might like
yii数据库的查询方法
2015/12/28 PHP
php preg_match的匹配不同国家语言实例
2016/12/29 PHP
PHP 实现页面静态化的几种方法
2017/07/23 PHP
PHP面向对象程序设计__tostring()和__invoke()用法分析
2019/06/12 PHP
javascript判断单选框或复选框是否选中方法集锦
2007/04/04 Javascript
javascript 混合的构造函数和原型方式,动态原型方式
2009/12/07 Javascript
点弹代码 点击页面任何位置都可以弹出页面效果代码
2012/09/17 Javascript
javascript和jquery修改a标签的href属性
2013/12/16 Javascript
Firefox下无法正常显示年份的解决方法
2014/09/04 Javascript
Javascript实现div的toggle效果实例分析
2015/06/09 Javascript
js实现不提交表单获取单选按钮值的方法
2015/08/21 Javascript
jQuery实现Flash效果上下翻动的中英文导航菜单代码
2015/09/22 Javascript
javascript伸缩型菜单实现代码
2015/11/16 Javascript
常用的几个JQuery代码片段
2017/03/13 Javascript
基于JavaScript实现图片连播和联级菜单实例代码
2017/07/28 Javascript
node中的密码安全(加密)
2018/09/17 Javascript
利用Electron简单撸一个Markdown编辑器的方法
2019/06/10 Javascript
node koa2 ssr项目搭建的方法步骤
2020/12/11 Javascript
[01:42]TI4西雅图DOTA2前线报道 第一顿早饭哦
2014/07/08 DOTA
[48:51]完美世界DOTA2联赛PWL S2 Magma vs InkIce 第一场 11.28
2020/12/02 DOTA
Python中XlsxWriter模块简介与用法分析
2018/04/24 Python
python接口自动化如何封装获取常量的类
2019/12/24 Python
浅谈多卡服务器下隐藏部分 GPU 和 TensorFlow 的显存使用设置
2020/06/30 Python
利用Python实现自动扫雷小脚本
2020/12/17 Python
详解CSS3 filter:drop-shadow滤镜与box-shadow区别与应用
2020/08/24 HTML / CSS
canvas绘图按照contain或者cover方式适配并居中显示
2019/02/18 HTML / CSS
利用异或运算实现两个无符号数的加法运算
2013/12/20 面试题
经贸日语专业个人求职信范文
2013/12/28 职场文书
纪念建党演讲稿范文
2014/01/13 职场文书
机关会计岗位职责
2014/04/08 职场文书
高考标语大全
2014/06/05 职场文书
实习护士自荐信
2014/06/21 职场文书
2014七年级班主任工作总结
2014/12/05 职场文书
2015年教师业务工作总结
2015/05/26 职场文书
初中班主任心得体会
2016/01/07 职场文书
2019年大学生职业生涯规划书
2019/03/25 职场文书