Как Pythonic сборщик мусора с массивом numpy добавляет и удаляет? - PullRequest
5 голосов
/ 07 августа 2010

Я пытаюсь адаптировать базовую структуру кода для построения графиков (matplotlib), которая обновляется по таймеру, чтобы переходить от использования списков Python для данных графика к использованию массивов-пустышек. Я хочу иметь возможность максимально сократить временной шаг графика, и, поскольку данные могут подняться до тысяч точек, я начинаю быстро терять драгоценное время, если не могу. Я знаю, что для такого рода вещей предпочтительнее использовать массивы numpy, но мне трудно понять, когда мне нужно думать как программист на Python и когда мне нужно думать как программист на C ++, максимально повысить эффективность доступа к памяти.

В документации scipy.org для функции append () говорится, что она возвращает копию массивов, добавленных вместе. Все эти копии правильно собираются? Например:

import numpy as np

a = np.arange(10)
a = np.append(a,10)
print a

Это мое прочтение того, что происходит на уровне C ++, но если бы я знал, о чем говорю, я бы не стал задавать вопрос, поэтому, пожалуйста, поправьте меня, если я ошибаюсь! = Р

Сначала выделяется блок из 10 целых чисел, а символ a указывает на начало этого блока. Затем выделяется новый блок из 11 целых чисел, что в сумме составляет 21 дюйм (84 байта). Затем указатель перемещается в начало блока 11-int. Я предполагаю, что это приведет к тому, что алгоритм сборки мусора уменьшит счетчик ссылок блока 10-int до нуля и отменит его выделение. Это правильно? Если нет, то как мне убедиться, что я не создаю накладные расходы при добавлении?

Я также не уверен, как правильно удалить массив numpy, когда я его использую. У меня на графике есть кнопка сброса, которая просто сбрасывает все данные и запускается заново. Когда у меня были списки, это было сделано с помощью del data[:]. Есть ли эквивалентная функция для массивов numpy? Или я должен просто сказать data = np.array ([]) и рассчитывать на сборщика мусора, который сделает всю работу за меня?

1 Ответ

10 голосов
/ 07 августа 2010

Смысл автоматического управления памятью в том, что вы не думаете об этом. В коде, который вы написали, копии будут хорошо собираться (почти невозможно запутать управление памятью в Python). Однако, поскольку np.append не на месте, код создаст в памяти новый массив (содержащий конкатенацию a и 10), а затем переменная a будет обновлена, чтобы указывать на этот новый массив , Поскольку a теперь больше не указывает на исходный массив, у которого был refcount 1, его refcount уменьшается до 0, и он будет очищен автоматически. Вы можете использовать gc.collect для принудительной полной очистки.

Сила Python не в тонкой настройке доступа к памяти, хотя ее можно оптимизировать. Скорее всего, вы предварительно отсортировали a (например, a = np.zeros( <size> )); если вам нужна более тонкая настройка, чем это, он начинает становиться немного волосатым. Вы могли бы взглянуть на Cython + Numpy учебное пособие для очень аккуратного и простого способа интеграции C с Python для эффективности.

Переменные в Python просто указывают на место, где хранится их содержимое; Вы можете del любую переменную, и она уменьшит количество ссылок своей цели на единицу. Цель будет очищена автоматически после того, как ее счетчик ссылок достигнет нуля. Мораль этого в том, что не беспокойтесь о том, чтобы очистить вашу память. Это произойдет автоматически.

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