Распределение памяти профиля в Python (с поддержкой массивов Numpy) - PullRequest
27 голосов
/ 30 июля 2010

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

Я ищу хороший профилировщик, который позволил бы мнечтобы проверить количество памяти, используемой различными объектами (я предполагаю аналог памяти cProfile), чтобы я знал, где оптимизировать.

Я слышал приличные вещи о Heapy, но Heapy, к сожалению, не поддерживаетNumpy массивы, и большая часть моей программы включает в себя Numpy массивы.

Ответы [ 5 ]

12 голосов
/ 11 октября 2013

Один из способов решения этой проблемы, если вы вызываете множество различных функций и не уверены в том, откуда происходит перестановка, - это использовать новую функцию построения графиков из memory_profiler .Сначала вы должны украсить различные функции, которые вы используете, с помощью @profile.Для простоты я буду использовать пример examples / numpy_example.py , поставляемый с memory_profiler, который содержит две функции: create_data() и process_data()

Для запуска вашего сценария вместо запуска его синтерпретатор Python, вы используете исполняемый файл mprof, то есть

$ mprof run examples/numpy_example.py

Это создаст файл с именем mprofile_??????????.dat, где?будет содержать числа, представляющие текущую дату.Чтобы отобразить результат, просто наберите mprof plot, и он сгенерирует график, похожий на этот (если у вас есть несколько файлов .dat, он всегда займет последний):

output of memory_profiler's mprof

Здесь вы видите потребление памяти со скобками, указывающими, когда вы входите / выходите из текущей функции.Таким образом, легко увидеть, что функция process_data() имеет пик потребления памяти.Чтобы углубиться в свою функцию, вы можете использовать построчное профилирование, чтобы увидеть потребление памяти каждой строкой в ​​вашей функции.Это выполняется с

python -m memory_profiler examples/nump_example.py

Это даст вам вывод, подобный следующему:

Line #    Mem usage    Increment   Line Contents
================================================
    13                             @profile
    14  223.414 MiB    0.000 MiB   def process_data(data):
    15  414.531 MiB  191.117 MiB       data = np.concatenate(data)
    16  614.621 MiB  200.090 MiB       detrended = scipy.signal.detrend(data, axis=0)
    17  614.621 MiB    0.000 MiB       return detrended

, где ясно, что scipy.signal.detrend выделяет огромный объем памяти.

10 голосов
/ 09 октября 2013

Посмотрите на профилировщик памяти . Он обеспечивает построчное профилирование и Ipython интеграцию, что делает его очень простым в использовании:

In [1]: import numpy as np

In [2]: %memit np.zeros(1e7)
maximum of 3: 70.847656 MB per loop

Обновление

Как упомянуто @WickedGrey, похоже, что есть ошибка ( см. Github track tracker ) при вызове функции более одного раза, которую я могу воспроизвести:

In [2]: for i in range(10):
   ...:     %memit np.zeros(1e7)
   ...:     
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.894531 MB per loop
maximum of 1: 70.902344 MB per loop
maximum of 1: 70.902344 MB per loop
maximum of 1: 70.902344 MB per loop
maximum of 1: 70.902344 MB per loop

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

1 голос
/ 01 июля 2014

Начиная с версии 1.7, существует полу-встроенный способ отслеживания выделения памяти:

https://github.com/numpy/numpy/tree/master/tools/allocation_tracking

0 голосов
/ 15 октября 2013

Вы пробовали valgrind с помощью инструмента massif?

valgrind --tool=massif python yourscript.py

, он создаст файл с именем massif.out.xxx, который можно просмотреть с помощью

ms_print massif.out.xxx | less

, который у него естьвсе виды полезной информации, но сюжет в самом начале должен быть тем, что вы ищете.Также посмотрите учебник по массиву на домашней странице valgrind.

Использование valgrind довольно продвинуто, и, возможно, есть более простые способы сделать то, что вы ищете.

0 голосов
/ 30 июля 2010

Можете ли вы просто сохранить / выбрать некоторые массивы на диск в файлах tmp, когда они не используются?Это то, что я должен был сделать в прошлом с большими массивами.Конечно, это замедлит работу программы, но, по крайней мере, она закончится.Разве вы не нуждаетесь в них сразу?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...