[英]Matplotlib memory leak when saving figure in a loop
我正在处理一个大数据集,我需要在每个数据点创建和导出图像。 我在过程中间左右达到了 memory 饱和度。 我应用了一些 memory 管理工具和库,发现存在 memory 泄漏,显然来自 matplotlib。 我已经尝试过垃圾收集器,删除循环中的所有变量,甚至在保存后删除图形,但 memory 在每次迭代中不断增加。 这里的代码,逐行memory分析和“tracemalloc”对memory的前10个影响
displacement=['Double sinus','Linear','Sinus in X','Sinus in Y']
os.chdir('E:\\Quality\\Magnitude')
disp_axis=[1,1,0,1]
import gc
from matplotlib import figure
import tracemalloc
tracemalloc.start(10)
for a in range(len(Folder_u)):
for b in range(len(Folder_u[a])):
u_exp = pd.read_csv(Folder_u[a][b],header=None,delimiter=' ',engine='pyarrow')
v_exp = pd.read_csv(Folder_v[a][b],header=None,delimiter=' ',engine='pyarrow')
TH_u = pd.read_csv(u_th[b],sep=',',header=None,engine='pyarrow')
TH_v = pd.read_csv(v_th[b],sep=',',header=None,engine='pyarrow')
M_exp = np.sqrt(u_exp.dropna(axis=1)**2+v_exp.dropna(axis=1)**2)
M_th = np.sqrt(TH_u**2+TH_v**2)
Error = abs(M_exp-M_th)/M_th *100
MM_E = Error.mean(axis=disp_axis[b])
MM_exp = M_exp.mean(axis=disp_axis[b])
MM_th = M_th.mean(axis=disp_axis[b])
name = N[a]
title=name.replace('.json','')
xth = np.linspace(0,len(MM_th),len(MM_th))
xe = np.linspace(0,len(MM_exp),len(MM_exp))
## mean error
#fig=figure.Figure(figsize=(15,10))
#ax = fig.subplots(1)
fig,ax = plt.subplots(figsize=(15,10))
plt.title('displacement = '+displacement[b]+', Config = ' + title ,fontsize=20,fontweight='bold')
#plt.title(Pyr_Type[l]+displacement[j])
ax.plot(MM_E,'b')
plt.ylim([0,100])
plt.yticks(np.linspace(0,100,11))
plt.ylabel('mean magnitude error [%]',fontsize=14)
plt.xlabel('Pixels',fontsize=14)
plt.grid()
#plt.ylim([0,5])
ax1=ax.twinx()
ax1.plot(xth,MM_th,'k',xe,MM_exp,'r-.')
plt.ylim([0,23])
plt.ylabel('mean displacement magnitude [Pixels]',fontsize=14)
plt.xlabel('Pixels',fontsize=14)
#plt.ylim([4,23])
#fig.set_dpi(300)
plt.grid()
fig.legend(['Mean error','Theoretical','Results'],fontsize=14,loc='upper right')
fig.set_dpi(250)
plt.show(fig)
plt.savefig('Mean_error_'+title+'_'+str(b)+'.png')
print(a)
del u_exp
del v_exp
del TH_u
del TH_v
del M_exp
del M_th
del Error
del MM_E
del MM_exp
del MM_th
del fig
del ax, ax1, name, title, xth,xe
gc.collect()
print('deleted')
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
tracemalloc.clear_traces()
这里对memory逐行分解分析:
Line # Mem usage Increment Occurrences Line Contents
=============================================================
241 2261.1 MiB 2261.1 MiB 1 @profile
242
243 def test():
244
245
246
247 #Pyr_Type = ['Haar (old)','Haar (NPP)','Burt (old)','Burt (new,old conv.)','Burt (new,new conv.)','Burt(NPP)']
248 2261.1 MiB 0.0 MiB 1 displacement=['Double sinus','Linear','Sinus in X','Sinus in Y']
249 2261.1 MiB 0.0 MiB 1 os.chdir('E:\\Quality\\Magnitude')
250 2261.1 MiB 0.0 MiB 1 disp_axis=[1,1,0,1]
251 2261.1 MiB 0.0 MiB 1 import gc
252 # from matplotlib import figure
253
254 2261.1 MiB 0.0 MiB 1 import tracemalloc
255 2261.1 MiB 0.0 MiB 1 tracemalloc.start(10)
256
257
258
259
260
261 2432.0 MiB 0.0 MiB 2 for a in range(1):
262 2432.0 MiB 0.0 MiB 5 for b in range(len(Folder_u[a])):
263 2361.8 MiB -34.9 MiB 4 u_exp = pd.read_csv(Folder_u[a][b],header=None,delimiter=' ',engine='pyarrow')
264 2361.0 MiB 2.0 MiB 4 v_exp = pd.read_csv(Folder_v[a][b],header=None,delimiter=' ',engine='pyarrow')
265 2399.2 MiB 110.1 MiB 4 TH_u = pd.read_csv(u_th[b],sep=',',header=None,engine='pyarrow')
266 2402.3 MiB 6.8 MiB 4 TH_v = pd.read_csv(v_th[b],sep=',',header=None,engine='pyarrow')
267 2433.4 MiB 126.2 MiB 4 M_exp = np.sqrt(u_exp.dropna(axis=1)**2+v_exp.dropna(axis=1)**2)
268 2464.9 MiB 124.5 MiB 4 M_th = np.sqrt(TH_u**2+TH_v**2)
269 2495.9 MiB 125.0 MiB 4 Error = abs(M_exp-M_th)/M_th *100
270 2495.9 MiB 0.0 MiB 4 MM_E = Error.mean(axis=disp_axis[b])
271 2495.9 MiB 0.0 MiB 4 MM_exp = M_exp.mean(axis=disp_axis[b])
272 2495.9 MiB 0.0 MiB 4 MM_th = M_th.mean(axis=disp_axis[b])
273
274 2495.9 MiB 0.0 MiB 4 name = N[a]
275 2495.9 MiB 0.0 MiB 4 title=name.replace('.json','')
276
277 2495.9 MiB 0.0 MiB 4 xth = np.linspace(0,len(MM_th),len(MM_th))
278 2495.9 MiB 0.0 MiB 4 xe = np.linspace(0,len(MM_exp),len(MM_exp))
279 ## mean error
280
281 #fig=figure.Figure(figsize=(15,10))
282 #ax = fig.subplots(1)
283 2497.9 MiB -27.5 MiB 4 fig,ax = plt.subplots(figsize=(15,10))
284
285 2497.9 MiB 0.0 MiB 4 plt.title('displacement = '+displacement[b]+', Config = ' + title ,fontsize=20,fontweight='bold')
286 #plt.title(Pyr_Type[l]+displacement[j])
287 2497.9 MiB 0.0 MiB 4 ax.plot(MM_E,'b')
288 2497.9 MiB 0.0 MiB 4 plt.ylim([0,100])
289 2499.9 MiB 10.0 MiB 4 plt.yticks(np.linspace(0,100,11))
290 2499.9 MiB 0.0 MiB 4 plt.ylabel('mean magnitude error [%]',fontsize=14)
291 2499.9 MiB 0.0 MiB 4 plt.xlabel('Pixels',fontsize=14)
292 2499.9 MiB 0.0 MiB 4 plt.grid()
293 #plt.ylim([0,5])
294
295 2499.9 MiB 0.0 MiB 4 ax1=ax.twinx()
296 2499.9 MiB 0.1 MiB 4 ax1.plot(xth,MM_th,'k',xe,MM_exp,'r-.')
297 2499.9 MiB 0.3 MiB 4 plt.ylim([0,23])
298 2499.9 MiB 4.0 MiB 4 plt.ylabel('mean displacement magnitude [Pixels]',fontsize=14)
299 2499.9 MiB 0.0 MiB 4 plt.xlabel('Pixels',fontsize=14)
300
301 2499.9 MiB 0.5 MiB 4 plt.grid()
302 2503.9 MiB 10.1 MiB 4 fig.legend(['Mean error','Theoretical','Results'],fontsize=14,loc='upper right')
303
304 2519.8 MiB 61.8 MiB 4 plt.savefig('Mean_error_'+title+'_'+str(b)+'.png',dpi=300)
305 2535.6 MiB 71.6 MiB 4 plt.show()
306 2535.6 MiB 0.0 MiB 4 print(a)
307
308 #fig.clear()
309 #plt.close()
310 #plt.cla()
311 2535.6 MiB 0.0 MiB 4 del u_exp
312 2535.6 MiB 0.0 MiB 4 del v_exp
313 2535.6 MiB 0.0 MiB 4 del TH_u
314 2535.6 MiB 0.0 MiB 4 del TH_v
315 2504.5 MiB -124.0 MiB 4 del M_exp
316 2473.5 MiB -124.0 MiB 4 del M_th
317 2442.5 MiB -124.0 MiB 4 del Error
318 2442.5 MiB 0.0 MiB 4 del MM_E
319 2442.5 MiB 0.0 MiB 4 del MM_exp
320 2442.5 MiB 0.0 MiB 4 del MM_th
321 2442.5 MiB 0.0 MiB 4 del fig
322 2442.5 MiB 0.0 MiB 4 del ax, ax1, name, title, xth,xe
323 2440.0 MiB -13.0 MiB 4 gc.collect()
324 2440.0 MiB 0.0 MiB 4 print('deleted')
325 2440.0 MiB 7.7 MiB 4 snapshot = tracemalloc.take_snapshot()
326 2440.0 MiB -2.8 MiB 4 top_stats = snapshot.statistics('lineno')
327 2432.0 MiB -42.0 MiB 4 tracemalloc.clear_traces()
328
329 #break
330
331 #break
332 #plt.show()
这里是 tracemalloc 的前 10 名:
C:\Users\user\AppData\Roaming\Python\Python39\site-packages\pandas\core\internals\blocks.py:402: size=62.0 MiB, count=5, average=12.4 MiB
C:\Users\user\anaconda3\lib\site-packages\numexpr\necompiler.py:836: size=31.0 MiB, count=2, average=15.5 MiB
C:\Users\user\AppData\Roaming\Python\Python39\site-packages\pandas\core\indexes\base.py:2237: size=194 KiB, count=17, average=11.4 KiB
C:\Users\user\anaconda3\lib\selectors.py:315: size=144 KiB, count=5, average=28.8 KiB
C:\Users\user\anaconda3\lib\site-packages\numpy\core\_asarray.py:102: size=119 KiB, count=387, average=314 B
C:\Users\user\anaconda3\lib\linecache.py:137: size=114 KiB, count=1165, average=100 B
C:\Users\user\anaconda3\lib\site-packages\matplotlib\lines.py:377: size=97.0 KiB, count=45, average=2208 B
C:\Users\user\anaconda3\lib\site-packages\matplotlib\lines.py:672: size=95.9 KiB, count=28, average=3509 B
<unknown>:0: size=95.8 KiB, count=23, average=4264 B
C:\Users\user\anaconda3\lib\site-packages\matplotlib\text.py:265: size=90.6 KiB, count=42, average=2208 B
```````````
我的问题是你创造了大量的数字。 你可以尝试把
fig,ax = plt.subplots(figsize=(15,10))
在 for 嵌套 for 循环之外。 只创建一个图形。 然后使用
fig.clear()
在里面添加所有东西之前清除数字。
您还可以 plot for 循环外的第一个图形,并使用set_data
更新图形的数据。 如果保存图形,则不需要plt.show(fig)
。
我有同样的问题,以下解决方案有效:
import matplotlib
matplotlib.use('Agg')
资料来源: https://matplotlib.org/stable/faq/howto_faq.html#work-with-threads
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.