前言 最近用paddlepaddle,发现训练每个epoch时,内存都会增加几百兆,这明显就是出现了内存泄漏。python中内存泄露的原因比C++(一般就是动态内存分配)更加隐蔽,可以借助memory_profiler这个包监控python代码的内存使用。
安装 直接pip安装就完事了
1 pip install memory_profiler
简单使用 只需要在.py文件中导入memory_profiler包中的profiler方法,然后作为某个函数的装饰器,就能够记录该函数内部代码的内存使用情况了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 from memory_profiler import profileimport numpy as np@profile def count (): print ('+++++++++++' ) a = 0 ; b = 1 ; c = a + b print ('a+b=c' ) print ('{}+{}={}' .format (a, b, c)) print ('+++++++++++' ) arr = np.ones([1000 , 1000 ]) print (arr.shape) print ('+++++++++++' ) if __name__ == '__main__' : count()
然后运行:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 +++++++++++ a+b=c 0+1=1 +++++++++++ (1000, 1000) +++++++++++ Filename: learn_mprof.py Line # Mem usage Increment Occurrences Line Contents ============================================================= 4 53.4 MiB 53.4 MiB 1 @profile 5 def count(): 6 53.4 MiB 0.0 MiB 1 print('+++++++++++') 7 53.4 MiB 0.0 MiB 1 a = 0; 8 53.4 MiB 0.0 MiB 1 b = 1; 9 53.4 MiB 0.0 MiB 1 c = a + b 10 53.4 MiB 0.0 MiB 1 print('a+b=c') 11 53.4 MiB 0.0 MiB 1 print('{}+{}={}'.format(a, b, c)) 12 53.4 MiB 0.0 MiB 1 print('+++++++++++') 13 61.1 MiB 7.7 MiB 1 arr = np.ones([1000, 1000]) 14 61.1 MiB 0.0 MiB 1 print(arr.shape) 15 61.1 MiB 0.0 MiB 1 print('+++++++++++')
Mem usage表示当前内存使用,Increment表示该行代码的内存增量,Occurences表示该行代码运行了几次。
如果要找内存泄漏,直接看Increment就OK了;如果想找内存瓶颈,就看Mem usage。
记录时间-内存的使用情况 如果想记录.py文件运行时,内存使用随时间的变化,也很简单,直接运行:
1 mprof run learn_mprof.py
输出结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 mprof: Sampling memory every 0.1s running new process running as a Python program... +++++++++++ a+b=c 0+1=1 +++++++++++ (1000, 1000) +++++++++++ Filename: learn_mprof.py Line # Mem usage Increment Occurrences Line Contents ============================================================= 4 53.6 MiB 53.6 MiB 1 @profile 5 def count(): 6 53.6 MiB 0.0 MiB 1 print('+++++++++++') 7 53.6 MiB 0.0 MiB 1 a = 0; 8 53.6 MiB 0.0 MiB 1 b = 1; 9 53.6 MiB 0.0 MiB 1 c = a + b 10 53.6 MiB 0.0 MiB 1 print('a+b=c') 11 53.6 MiB 0.0 MiB 1 print('{}+{}={}'.format(a, b, c)) 12 53.6 MiB 0.0 MiB 1 print('+++++++++++') 13 61.3 MiB 7.7 MiB 1 arr = np.ones([1000, 1000]) 14 61.3 MiB 0.0 MiB 1 print(arr.shape) 15 61.3 MiB 0.0 MiB 1 print('+++++++++++')
此时,在运行目录中会多出一个mprofile_xxxxxxxxxxxx.dat文件,可以通过这个文件画出时间-内存图:
1 mprof plot mprofile_xxxxxxxxxxxxxxxx.dat
效果: