2010-09-02 55 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