Подтвердить что ты не робот

Позволяет ли освобождение обрабатываться по-разному для небольших/больших массивов numpy?

Я пытаюсь отладить проблему памяти с моим большим приложением Python. Большая часть памяти находится в массивах numpy, управляемых классами Python, поэтому Heapy и т.д. Бесполезны, поскольку они не учитывают память в массивах numpy, Поэтому я попытался вручную отслеживать использование памяти с помощью монитора активности MacOSX (10.7.5) (или top, если хотите). Я заметил следующее странное поведение. На обычной интерпретаторной интерпретации python (2.7.3):

import numpy as np # 1.7.1
# Activity Monitor: 12.8 MB
a = np.zeros((1000, 1000, 17)) # a "large" array
# 142.5 MB
del a
# 12.8 MB (so far so good, the array got freed)
a = np.zeros((1000, 1000, 16)) # a "small" array
# 134.9 MB
del a
# 134.9 MB (the system didn't get back the memory)
import gc
gc.collect()
# 134.9 MB

Независимо от того, что я делаю, объем памяти в сеансе Python никогда не будет ниже 134,9 МБ. Поэтому мой вопрос:

Почему ресурсы массивов размером более 1000x1000x17x8 байт (найденные эмпирически в моей системе) должным образом возвращены системе, а память меньших массивов, похоже, навсегда застряла с интерпретатором Python?

Это, по-видимому, улучшает работу, поскольку в моих реальных приложениях я получаю более 2 ГБ памяти, я никогда не смогу вернуться из интерпретатора Python. Является ли это предполагаемым поведением, что Python резервирует все больше и больше памяти в зависимости от истории использования? Если да, то Activity Monitor так же бесполезен, как Heapy для моего дела. Есть ли что-то, что не бесполезно?

4b9b3361

Ответ 1

Чтение из Политика Numpy для выпуска памяти кажется, что numpy не имеет специальной обработки выделения/освобождения памяти. Он просто вызывает free(), когда счетчик ссылок обращается в ноль. На самом деле довольно легко реплицировать проблему с помощью любого встроенного объекта python. Проблема заключается в уровне ОС.

Натаниел Смит написал объяснение того, что происходит в одном из его ответов в связанной теме:

В общем случае процессы могут запрашивать память из ОС, но они не могут отдай это обратно. На уровне C, если вы вызываете free(), то что на самом деле происходит то, что библиотека управления памятью в вашем процессе делает обратите внимание на то, что эта память не используется и может вернуть ее из будущее malloc(), но с точки зрения OS это все еще "Выделено". (И python использует другую подобную систему сверху malloc()/free(), но это ничего не меняет.) Итак, ОС использование памяти, которое вы видите, обычно представляет собой "знак высокой воды", максимальный объем памяти, необходимый вашему процессу.

Исключением является то, что для больших одиночных распределений (например, если вы создаете массив с несколькими мегабайтами) используется другой механизм. Такие большие выделения памяти могут быть возвращены обратно в ОС. Так что это может в частности, это не те numpy части вашей программы, которые производят проблемы, которые вы видите.

Итак, похоже, что нет общего решения проблемы. Выделение многих небольших объектов приведет к "высокому использованию памяти", как профилируемым инструментами, даже если вы будете повторно использовать их при необходимости, а выделение больших объектов не будет показать большое использование памяти после освобождения, поскольку память восстанавливается ОС.

Вы можете проверить это выделение встроенных объектов python:

In [1]: a = [[0] * 100 for _ in range(1000000)]

In [2]: del a

После этого кода я вижу, что память не восстанавливается, делая:

In [1]: a = [[0] * 10000 for _ in range(10000)]

In [2]: del a

память исправлена.

Чтобы избежать проблем с памятью, вы должны либо выделять большие массивы, либо работать с ними (возможно, использовать представления для "имитации" небольших массивов?) или пытаться избежать одновременного использования множества небольших массивов. Если у вас есть цикл, который создает небольшие объекты, вы можете явно освобождать объекты, которые не нужны на каждой итерации, а не делать это только в конце.


Я полагаю, что Python Memory Management дает хорошее представление о том, как управление памятью в python. Обратите внимание, что в дополнение к "проблеме ОС" python добавляет еще один уровень для управления аренами памяти, что может способствовать высокому использованию памяти небольшими объектами.