【问题标题】:Python matplotlib: memory not being released when specifying figure sizePython matplotlib:指定图形大小时未释放内存
【发布时间】:2011-04-07 02:52:48
【问题描述】:

我正在使用 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()

问题在于,每次调用此函数时,python 进程的内存使用量都会增加几兆字节。例如,如果我用这个循环调用它:

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) 是默认图形大小,因此在两种情况下都会生成相同的图像。我想从我的数值数据中制作不同大小的图,而不会用完 ram。我如何强制 python 释放这个内存?

我试过gc.collect()每个循环强制垃圾回收,我试过f = gcf()获取当前数字,然后del f删除它,但无济于事。

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

【问题讨论】:

    标签: python memory-management matplotlib


    【解决方案1】:

    来自pylab.figure 的文档字符串:

    In [313]: pylab.figure?
    

    如果您要创建许多图形,请制作 确保您明确调用“关闭” 你没有使用的数字,因为 这将使 pylab 能够正确 清理内存。

    所以不妨试试:

    pylab.close()     # closes the current figure
    

    【讨论】:

    • 就是这样!非常感谢。
    • 是的,clf 不会删除图窗或释放其资源,它只会清除它。而f = gcf(); del f 只会删除您刚刚创建的引用,不会删除图形对象本身。这就是您需要close 的目的。 (+1)
    【解决方案2】:

    关闭一个数字绝对是一种选择,但是,重复多次,这很耗时。我的建议是拥有一个持久的图形对象(通过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
    

    【讨论】:

    • 不错。现在我很清楚,在我的原始示例中,每次调用 figure() 时,我都在创建一个新图形,而不是关闭旧图形。除了参考参考之外,还可以提供数字参数:figure(0,figsize=whatever) 以确保每次都使用相同的数字。
    猜你喜欢
    • 2018-05-29
    • 2011-10-29
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2016-03-18
    • 1970-01-01
    • 2015-06-21
    • 2015-04-14
    相关资源
    最近更新 更多