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