Могу ли я узнать запрос на выделение памяти, вызвавший мой Python MemoryError? - PullRequest
0 голосов
/ 20 сентября 2018

Контекст

Мой маленький скрипт на Python использует библиотеку для работы с некоторыми относительно большими данными.Стандартным алгоритмом для этой задачи является алгоритм динамического программирования, поэтому, предположительно, библиотека «под капотом» выделяет большой массив для отслеживания частичных результатов DP.Действительно, когда я пытаюсь дать ему достаточно большой ввод, он сразу дает MemoryError.

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

Вопрос

Когда мой код Python выдает MemoryError, есть ли «нисходящий» способ для моего исследованиякакой объем памяти пытался выделить мой код, что вызвало ошибку, например, путем проверки объекта ошибки?

Ответы [ 3 ]

0 голосов
/ 17 ноября 2018

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

Вы также не можете точно знать, сколько памяти потребуется для успешного выполнения всей операции.Если библиотека создает несколько структур данных в ходе работы, попытка выделить память для строки, используемой в качестве ключа словаря, может быть последней каплей или копированием всей существующей структуры данных для мутации или чего-либо промежуточного, ноэто ничего не говорит о том, сколько памяти потребуется, кроме того, для оставшейся части процесса.

Тем не менее, Python может дать вам подробную информацию о том, какие выделения памяти производятся, икогда и где, используя модуль tracemalloc .Используя этот модуль и экспериментальный подход, вы можете оценить, сколько памяти потребуется вашему набору данных.

Хитрость заключается в том, чтобы найти наборы данных, для которых процесс может быть завершен.Вы хотели бы найти наборы данных разных размеров, и затем вы можете измерить, сколько памяти требуется для этих структур данных.Вы создадите моментальные снимки до и после с помощью tracemalloc.take_snapshot(), сравните различия и статистику между моментальными снимками для этих наборов данных, и, возможно, вы сможете экстраполировать из этой информации, насколько больше памятибольший набор данных потребуется.Конечно, это зависит от характера операции и наборов данных, но если есть какая-либо схема, tracemalloc - лучший способ ее обнаружить.

0 голосов
/ 19 ноября 2018

Вы можете увидеть распределение памяти с помощью Pyampler , но вам нужно будет добавить операторы отладки локально в используемую библиотеку.Предполагая стандартный пакет PyPi, выполните следующие шаги:

  1. Клонируйте пакет локально.

2 Используйте сводный модуль Pyampler.Поместите следующее в основной метод рекурсии,

   from pympler import summary
   def data_intensive_method(data_xyz)
       sum1 = summary.summarize(all_objects)
       summary.print_(sum1)
       ...
Запустите pip install -e . для локальной установки отредактированного пакета. Запустите основную программу и проверяйте консоль на предмет использования памяти на каждой итерации.
0 голосов
/ 17 ноября 2018

Похоже, что MemoryError не создается с какими-либо связанными данными:

def crash():
    x = 32 * 10 ** 9
    return 'a' * x

try:
    crash()
except MemoryError as e:
    print(vars(e))  # prints: {}

Это имеет смысл - как это может быть, если не осталось памяти?

Я не думаю,есть простой выход.Вы можете начать с трассировки, которую MemoryError вызывает и исследовать с помощью отладчика, или использовать профилировщик памяти, например pympler (или psutil, как предлагается в комментариях).

...