Python matplotlib: память не освобождается при указании размера фигуры - PullRequest
25 голосов
/ 02 сентября 2010

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

Ответы [ 2 ]

35 голосов
/ 02 сентября 2010

Из строки документации для pylab.figure:

In [313]: pylab.figure?

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

Так что, возможно, попробуйте:

pylab.close()     # closes the current figure
9 голосов
/ 14 декабря 2011

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