发布时间:2022-11-21 09:00
有一个NLP相关的代码放在实验室的服务器上跑的时候,刚开始非常快,几分钟可以跑70个例子,过了几小时后就明显变慢,甚至放在服务器上跑了一晚上,仍然只跑了几个,因此,肯定不是代码本身的功能或者例子本身的问题。
问了实验室的同学,应该是发生了内存泄漏。
内存泄漏(Memory Leak)是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。我的程序正好有大量的循环,因此也给不断累积的内存泄漏提供了条件。
如果是在服务器中,可以使用top命令查看一下运行中的程序的实时变化,非常明显的我就可以看到,在使用内存这一项上,我的程序初始运行时是2.9g,但是运行过程中会不断增长,如果过了几个小时看,所占的内存就是5.5g了,这个证据就明显的说明了我的程序发生了内存泄漏,无怪乎程序越来越慢。
那么为了解决这个问题,最主要的还是要定位程序中哪一个部分发生了泄露,才可以做出修改。
这里要使用到objgraph。
其中objgraph.show_growth()可以显示出代码执行过后增加的对象。
tuple 163411 +8749
list 4056757 +2709
dict 48076 +1665
Operation 5235 +429
_InputList 5235 +429
Tensor 5414 +423
TF_Output 4650 +372
Dimension 1528 +207
TensorShapeV1 988 +174
TraceableObject 3863 +120
这就是我每次循环过后增长的对象,可以看到内存泄漏的情况还是蛮严重的。
objgraph.show_chain(objgraph.find_backref_chain(objgraph.by_type('list')[0],objgraph.is_proper_module),filename='list.dot' )
这句代码可以将程序中的引用关系找出来,生成一个dot文件来记录,使用graphviz软件可以绘制成图。
https://www.cnblogs.com/xybaby/p/7491656.html
这个博客有详细的介绍。
最后问题发现在一个神经网络相关的代码中,由于tensorflow的图是静态图,但是如果直接加载不同的图(即不同的模型),应该都会存在内存中,原有的图并不会释放,因此造成了测试速度越来越慢。
我的代码在每次循环时都会调用一次预测模型,可能是在这个过程中没有注意导致了内存泄漏。只要每次用完模型得到结果后
from keras import backend as K
K.clear_session()
就可以清除session。防止内存泄漏啦。之后运行,内存也基本稳定在3g左右了。