2010-09-02 88 views
25

我正在使用matplotlib生成許多數值模擬結果圖。該地塊被用作一個視頻幀,所以我通過反覆調用函數與此類似生成許多人:python matplotlib:指定圖形大小時未釋放內存

from pylab import * 

def plot_density(filename,i,t,psi_Na): 
    figure(figsize=(8,6)) 
    imshow(abs(psi_Na)**2,origin = 'lower') 
    savefig(filename + '_%04d.png'%i) 
    clf() 

的問題是,蟒蛇進程的內存使用量增長由每次調用這個函數幾兆字節。例如,如果我用這個循環調用它:

if __name__ == "__main__": 
    x = linspace(-6e-6,6e-6,128,endpoint=False) 
    y = linspace(-6e-6,6e-6,128,endpoint=False) 
    X,Y = meshgrid(x,y) 
    k = 1000000 
    omega = 200 
    times = linspace(0,100e-3,100,endpoint=False) 
    for i,t in enumerate(times): 
     psi_Na = sin(k*X-omega*t) 
     plot_density('wavefunction',i,t,psi_Na) 
     print i 

然後內存使用量隨着時間增長到600MB。但是,如果我在函數定義中註釋掉figure(figsize=(8,6))行,那麼RAM的使用率保持穩定在52MB。 (8,6)是默認的圖形尺寸,因此在兩種情況下都會生成相同的圖像。我想從我的數字數據中製作不同大小的圖表,而不會耗盡內存。我該如何強制python釋放這些內存?

我試過gc.collect()每個循環強制垃圾回收,我試過f = gcf()得到當前數字,然後del f刪除它,但無濟於事。

我在64位Ubuntu 10.04上運行CPython 2.6.5。

回答

35

從文檔字符串爲pylab.figure

In [313]: pylab.figure? 

如果要創建許多數字,讓 一定要明確地稱之爲「接近」於 您使用的不是數字,因爲 這將使pylab正確地 清理內存。

因此,也許嘗試:

pylab.close()  # closes the current figure 
+0

這就行了!非常感謝。 – 2010-09-02 03:27:54

+2

是的,'clf'不會刪除這個數字或釋放它的資源,它只會清除它。和'f = gcf(); del f'只會刪除剛剛創建的引用,並不會刪除圖形對象本身。這就是你需要「關閉」的。 (+1) – 2010-09-02 04:56:27

9

關閉這個數字絕對是一個選項,但是,反覆多次,這是費時。我建議的是擁有一個持久數字對象(通過static function variable或作爲附加函數參數)。如果該對象是fig,則函數將在每個繪圖週期之前調用fig.clf()之前的

from matplotlib import pylab as pl 
import numpy as np 

TIMES = 10 
x = np.linspace(-10, 10, 100) 
y = np.sin(x) 
def withClose(): 
    def plotStuff(i): 
     fig = pl.figure() 
     pl.plot(x, y + x * i, '-k') 
     pl.savefig('withClose_%03d.png'%i) 
     pl.close(fig) 
    for i in range(TIMES): 
     plotStuff(i) 


def withCLF(): 
    def plotStuff(i): 
     if plotStuff.fig is None: 
      plotStuff.fig = pl.figure() 
     pl.clf() 
     pl.plot(x, y + x * i, '-') 
     pl.savefig('withCLF_%03d.png'%i) 
    plotStuff.fig = None 

    for i in range(TIMES): 
     plotStuff(i) 

這裏是時序值

In [7]: %timeit withClose() 
1 loops, best of 3: 3.05 s per loop 

In [8]: %timeit withCLF() 
1 loops, best of 3: 2.24 s per loop 
+1

不錯。現在很清楚,在我最初的例子中,每次調用'figure()',我都會創建一個新數字,而不是關閉舊數字。除了掛在引用上,還可以提供數字參數:'figure(0,figsize = whatever)'以確保每次都使用相同的數字。 – 2012-01-30 03:26:06