Ответ 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 добавляет еще один уровень для управления аренами памяти, что может способствовать высокому использованию памяти небольшими объектами.