#python #pandas #matplotlib #memory-leaks
#python #pandas #matplotlib #утечки памяти
Вопрос:
Я страдаю от утечки памяти в моем «цикле for (более 1100 циклов)» для создания карт. Я не могу определить, что так сильно требует памяти во время циклов. Когда я проверил, что может помочь — большинство подсказок commons должны были использовать:
plt.clf()
gc.collect()
ни то, ни другое не помогло.
Когда я проверяю циклы psutil.Process(os.getpid()).memory_info().rss / 1024 ** 2
на использование памяти, оно постоянно увеличивается на 31 МБ на цикл, даже если циклы не всегда одинаковы (существует 4 возможности / способа создания карт). objgraph
Я попытался определить, что накапливается в памяти, но я не могу точно определить, что происходит. Вот вывод из (objgraph.show_growth())
:
dict 20565 49
method 1034 26
list 6886 21
weakref 11206 20
tuple 11657 19
cell 6584 18
function 22611 17
builtin_function_or_method 5268 13
WeakMethod 232 7
Bbox 223 6
Вот пример кода (один из 4), который я использую для создания карт:
def plot_map_lin (boundry, colm_var, shp, code_name):
name_val = []
vmin = 9999999
vmax = 0
for row in range(lencodes):
cell = data.iloc[row][colm_var]
name_val.append(float(cell) abs(boundry[0]))
if float(cell) > vmax:
vmax = int(cell)
elif float(cell) < vmin:
vmin = int(cell)
gdfdict[colm_var] = name_val
df = pd.DataFrame(gdfdict)
map_df = gpd.read_file(shp)
map_df['KOD'] = map_df['KOD'].astype(int)
merge = map_df.merge(df, left_on = 'KOD', right_on = 'Kod')
fig, ax = plt.subplots(1, figsize = (40, 20))
cmap = mpl.cm.YlGn
norm = mpl.colors.Normalize(vmin = vmin, vmax = vmax)
cb = plt.colorbar(mpl.cm.ScalarMappable(norm = norm, cmap = cmap), orientation = 'vertical', format = mpl.ticker.FuncFormatter(format_ticks))
cb.set_label(label = label_name(code_name), size = 20)
merge.plot(column = colm_var, cmap = map_color, linewidth = 0.2, ax = ax, edgecolor = '0.5')
ax.set_title(map_name(colm_var), fontdict = {'fontsize': '35', 'fontweight' : '10'})
ax.axis('off')
name_of_map = "Linear" colm_var ".png"
plt.savefig(path_script "/Mapy/" name_of_map, dpi=100)
plt.clf()
gc.collect()
print(objgraph.show_growth())
print(psutil.Process(os.getpid()).memory_info().rss / 1024 ** 2)
Кто-нибудь знает, что не так, и, возможно, как это исправить?
Спасибо
Комментарии:
1. Действительно трудно сказать без вашего кода. Вы пробовали не отображать фигуру, но оставляли остальную часть цикла неизменной? т. Е. прокомментируйте все после
fig, ax = ...
и посмотрите, сохраняется ли утечка памяти? Например, в приведенном выше примере у вас есть куча глобальных переменных, которые, насколько я могу судить, могут легко увеличиваться в памяти в зависимости от того, насколько они великиdata
.2. Привет, я попробовал комментировать, как вы предлагали — 99% увеличения памяти и утечка вызваны этой строкой
plt.savefig(path_script "/Mapy/" name_of_map, dpi=100)
, но я не могу понять, почему. Когда у меня естьplt.clf()
,gc.collect()
а теперь иplt.close('all')
послеplt.savefig
, я подумал, что он должен очистить память от fig, но каким-то образом он застрял в нем.3. Я думаю, что застревание в памяти каким-то образом вызвано тем фактом, что в нем есть два графика,
fig, ax = plt.subplots(1, figsize = (40, 20))
и в конце он стирает только один из них. Не уверен в этом, и я даже не знаю, как это выяснить, потому что «fig» и «ax» недоступны после цикла.4. Это действительно трудно сказать без всего вашего кода. Предлагаю вам попытаться создать минимально воспроизводимый пример, и это либо сделает вещи очевидными, либо даст нам что-то для работы. Я подозреваю, что вы не закрываете все свои цифры.
Ответ №1:
Вы можете попробовать как plt.clf(), так и plt.cla()(очищая обе фигуры и оси соответственно).Если это не работает быстро (возможно, немного затратно по времени выполнения), это запустить вашу функцию как другой процесс, который умрет и очистит всю память в случае утечки памяти.
Комментарии:
1.
plt.cla()
также не имеет никакого эффектаplt.close()
,plt.close('all)
, и т.д.fig.clf()
Однако я обнаружил, что «застрявшая» память пропорционально равна размеру рисункаfig, ax = plt.subplots(1, figsize = (40, 20))
— когда я меняю 40, 20 на 20, 10 и, таким образом, уменьшаю fig в 4 раза, «застрявшая» память также в 4 раза меньше. Но пока никакого дальнейшего прогресса.