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

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

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

Я запускаю CPython 2.6.5 на 64-разрядном Ubuntu 10.04.

ответ

35

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

In [313]: pylab.figure? 

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

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

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

Это делает его! Огромное спасибо. –

+2

Да, 'clf' не удаляет фигуру или не отпускает ее ресурсы, она только очищает ее. И 'f = gcf(); del f' удаляет только что созданную ссылку, она не удаляет сам объект фигуры. Это то, что вам нужно «закрыть». (+1) –

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()' в моем исходном примере я создавал новую фигуру и не закрывал старую. Также, как и для ссылки, можно также указать аргумент number: 'figure (0, figsize = whatever)', чтобы гарантировать, что один и тот же показатель используется каждый раз. –

Смежные вопросы