Python matplotlib: память не выделяется при задании размера фигуры

Я использую 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

то использование плунжера растет со временем до 600 МБ. Если, однако, я прокомментирую строку figure(figsize=(8,6)) в определении функции, тогда использование плунжера остается устойчивым на уровне 52 МБ. (8,6) - это размер фигуры по умолчанию, и поэтому одинаковые изображения создаются в обоих случаях. Я хотел бы сделать графики разного размера из своих числовых данных, не исчерпываясь. Как я могу заставить python освободить эту память?

Я пробовал gc.collect() каждый цикл для принудительной сборки мусора, и я попробовал f = gcf(), чтобы получить текущую цифру, а затем del f, чтобы удалить ее, но безрезультатно.

Я запускаю CPython 2.6.5 на 64-битном Ubuntu 10.04.

Ответ 1

Из docstring для pylab.figure:

In [313]: pylab.figure?

Если вы создаете много цифр, сделайте убедитесь, что вы явно назовете "закрыть" цифры, которые вы не используете, потому что это позволит pylab правильно очистите память.

Итак, попробуйте:

pylab.close()     # closes the current figure

Ответ 2

Закрытие фигуры определенно является опцией, однако, повторяется много раз, это занимает много времени. Я предлагаю иметь один постоянный объект фигуры (через статическую функциональную переменную или как дополнительный аргумент функции). Если этот объект 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