2013-11-18 1 views
1

EDIT: решаемыеxPython savefig утечка памяти нерешенным с ранее предлагаемыми решениями

Но я не знаю, как ... я переехал столько, сколько я мог pylab вместо pyplot, реализован многопроцессорная подход, описанный [здесь] [1], и в этот момент он работал нормально. Затем, пытаясь определить проблему, я пошагово менял код. Но он продолжал работать, даже без многопроцессорности, даже с помощью pyplot и т. Д. Только когда я снимаю fig.clf(), теперь это не сработает, что, по-видимому, испытывает большинство людей, но изначально это не было проблемой. Ну, возможно, это было, может быть, заявление clf() не было в нужном месте или что-то в этом роде. Благодаря !

EDIT: ПРОБЛЕМА НЕ РЕШИТЬ ЕЩЕ

Это очень удивительно. Теперь я переместил мою функцию savefig() во внешний модуль, который я импортирую при выполнении моего скрипта. Вот функция:

def savethefig(fig,outpath,luname): 
    plt.savefig(outpath+luname+'testredtarget.png',dpi=500) 

Так что теперь я сделать что-то вроде:

from myfile import savethefig 
fig = plt.figure() 
ax1 = fig.add_subplot(311) 
pftmap=zeros(shape=(1800,3600))*nan 
    for i in range(len(pftspatialnames)): 
     pftmap[indlat,indlon]=data[i,:] 
     fig = pylab.gcf() 
     a1=ax1.imshow(pftmap, interpolation='nearest',origin='upper', aspect='auto') 
     savethefig(fig,outpath,luname) 

Я сделал все шаг за шагом, строка за строкой и ОЗУ определенно идет вверх, когда hiting функцию savefig() внутри внешняя функция. Подходит примерно на 500 МБ. Затем, возвращаясь к основному скрипту, эта память не будет выпущена. Разве внешняя функция не должна очищать все? Я что-то не хватает ...

ОРИГИНАЛЬНЫЙ ПОСТ:

Я использую питона EDP 7.3-2 (32 бит) (Python 2.7.3).

У меня есть программа, которая выполняет некоторые вычисления, затем отображает некоторые результаты и сохраняет изображения с помощью matplotlib.

Это довольно большой объем данных, и если я попытаюсь отобразить и сохранить слишком много изображений, я попал в пределы памяти. Который я не должен с тех пор, как повторно использовать ту же фигуру, и не создаю новых переменных. Я некоторое время боролся с этим, пробовал все способы очистки/удаления и т. Д. Решений, меняя бэкэнд, используемый matplotlib, но ничего не делает, каждый раз, когда код попадает в функцию savefig, он добавляет много памяти и не принимает это позже.

Я далеко не эксперт на вещи памяти (или питона, кстати), но вот одна диагностирует попытка я побежал, используя модуль objgraph:

from numpy import * 
import matplotlib 
matplotlib.use('Agg') 
from matplotlib.figure import Figure 
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas 
from matplotlib import pyplot as plt 

outpath = '/Users/yannick/Documents/outputs/' 
pftspatialnames = ['forest','shrubs','grass'] 

Computations (not shown) 

fig = plt.figure() 
for i in range(len(pftspatialnames)): 
    pftmap=zeros(shape=(1800,3600))*nan 
    pftmap[indlat,indlon]=data[i,:] 
    fig = pylab.gcf() 
    ax1 = plt.subplot2grid((3,1),(0,0)) 
    a1=ax1.imshow(pftmap, interpolation='nearest',origin='upper', aspect='auto') 
    del(pftmap) 
    gc.collect() 

    print 'MEMORY LEAK DETECTOR before figsave' 
    objgraph.show_growth() 

    plt.savefig(outpath+pftspatialnames[i]+'testredtarget.png', dpi=500) 

    print 'MEMORY LEAK DETECTOR after figsave' 
    objgraph.show_growth() 

Довольно большие карты (и есть 3 из них, 3 подзаголовка, просто показали один здесь), но он справляется с этим довольно хорошо. Для насыщения памяти требуется около 4 цифр. Некоторые вещи могут быть излишними (например, удаление pftmap), но я пытался все очистить память.

А вот печатная продукция:

MEMORY LEAK DETECTOR before figsave 
dict    6640  +2931 
weakref    3218  +1678 
instance   1440  +1118 
tuple    3501  +939 
function   12486  +915 
Bbox     229  +229 
instancemethod  684  +171 
Line2D    147  +147 
TransformedBbox  115  +115 
Path     127  +114 
MEMORY LEAK DETECTOR after figsave 
dict    7188  +548 
Path     422  +295 
weakref    3494  +276 
instance   1679  +239 
tuple    3703  +202 
function   12670  +184 
TransformedPath  87  +87 
instancemethod  741  +57 
Line2D    201  +54 
FontProperties  147  +36 

Так перед вызовом savefig есть много новых объектов (это нормально я сделать кучу вещей в коде раньше). Но тогда, просто позвонив savefig, мы добавим 550 dict и т. Д. Может ли это быть источником моей проблемы? Обратите внимание, что это происходит при первом вызове savefig. Любой последующий вызов делает следующее:

MEMORY LEAK DETECTOR before figsave 
MEMORY LEAK DETECTOR after figsave 
tuple  3721  +6 
dict   7206  +6 
function 12679  +3 
list   2001  +3 
weakref  3503  +3 
instance  1688  +3 
Bbox   260  +3 

но память все еще продолжает расти, и вскоре я нажму память.

Большое спасибо!

+0

Что произойдет, если вы gc.collect() 'между savefigs? – rickhg12hs

+0

Спасибо! Я фактически делаю gc.collect между фиг. –

+0

Путь к коду в сохранении зависит от того, какие художники на вашем рисунке. Предоставьте полный (но минимальный) код, чтобы продемонстрировать проблему. – tacaswell

ответ

0

EDIT: решаемые

Но я не знаю, как ... я переехал столько, сколько я мог pylab вместо pyplot, реализован многопроцессорная подход, описанный [здесь] [1] , и в этот момент он работал нормально. Затем, пытаясь определить проблему, я пошагово менял код. Но он продолжал работать, даже без многопроцессорности, даже с помощью pyplot и т. Д. Только когда я снимаю fig.clf(), теперь это не сработает, что, по-видимому, испытывает большинство людей, но изначально это не было проблемой. Ну, возможно, это было, может быть, заявление clf() не было в нужном месте или что-то в этом роде. Спасибо

0

Похоже, что доказательства, сделанные в Google, показывают, что выполнение «matplotlib.pyplot.close» после спасения позволит восстановить/освободить память, связанную с фигурой. См. Документацию pyplot для всех вызывающих опций.

0

Я забыл, что поток переполнения стека/веб-сайта Я нашел это решение, но использование фигуры напрямую (и не касаясь автомата для работы с пистолетом) обычно делает трюк. Итак:

fig = figure.Figure() 
canvas = FigureCanvas(fig) 
... 
canvas.print_figure(outpath+pftspatialnames[i]+'testredtarget.png', dpi=500) 
+0

Спасибо, я пробовал это и видел, что он был успешным для некоторых из-за проблем с памятью. В моем случае это не помогло. Наконец нашел решение, размещенное в исходном сообщении. –

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