numpy не будет перегружать память, даже если vm.overcommit_memory=1
Я сталкиваюсь с числовой ошибкойnumpy.core._exceptions.MemoryError
в моем коде. На моей машине достаточно свободной памяти, так что это не должно быть проблемой. (Это на Raspberry Pi Armv7l, 4 ГБ)
$ free
total used free shared buff/cache available
Mem: 3748172 87636 3384520 8620 276016 3528836
Swap: 1048572 0 1048572
Я нашел этот пост , в котором предлагалось разрешить overcommit_memory в ядре, и я так и сделал:
$ cat /proc/sys/vm/overcommit_memory
1
Теперь, когда я пытаюсь запустить этот пример:
import numpy as np
arrays = [np.empty((18, 602, 640), dtype=np.float32) for i in range(200)]
Я получаю ту же ошибку:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
numpy.core._exceptions.MemoryError: Unable to allocate 26.5 MiB for an array with shape (18, 602, 640) and data type float32
Почему Python (или numpy) ведет себя таким образом и как я могу заставить его работать?
РЕДАКТИРОВАТЬ: Ответы на вопросы в ответах:
Это 32-битная система (armv7l)
>>> sys.maxsize
2147483647
Я напечатал приблизительный размер (согласно сообщению об ошибке каждая итерация должна составлять 26,5 МБ), при котором пример не работает:
def allocate_arr(i):
print(i, i * 26.5)
return np.empty((18, 602, 640), dtype=np.float32)
arrays = [allocate_arr(i) for i in range(0, 200)]
Вывод показывает, что это не удается при выделении около 3 ГБ ОЗУ:
1 26.5
2 53.0
3 79.5
...
111 2941.5
112 2968.0
113 2994.5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <listcomp>
File "<stdin>", line 3, in allocate_arr
numpy.core._exceptions.MemoryError: Unable to allocate 26.5 MiB for an array with shape (18, 602, 640) and data type float32
3 ГБ это предел? Есть ли способ увеличить это? И не является ли это причиной перенапряжения?
2 ответа
По умолчанию в 32-разрядной версии Linux соотношение пользователей и ядра составляет 3:1. То есть из 4 ГБ, к которым можно обратиться с помощью 32-битного целого числа без знака, 3 ГБ зарезервировано для пользовательского пространства, а 1 ГБ зарезервировано для пространства ядра. Таким образом, любой отдельный процесс может использовать не более 3 ГБ памяти. Параметр vm.overcommit не имеет к этому отношения, т. е. используется больше виртуальной памяти, чем имеется фактической физической памяти, поддерживающей виртуальную память.
Раньше в ядре Linux существовала так называемая поддержка 4G/4G (не уверен, были ли когда-либо включены эти исправления?), позволяющая использовать полные 4 ГБ процессам пользовательского пространства и еще 4 ГБ адресного пространства ядру. ценой ухудшения производительности (очистка TLB при каждом системном вызове?). Но, AFAIU, эти функции устарели, поскольку все, кто заинтересован в использовании большого количества памяти, уже давно перешли на 64-битные системы.
Другие сталкивались с подобными проблемами в прошлом. Проблема сохраняется даже на64 bit OS
? Возможно, проблема связана с тем, что вы используете32-bit
система. В 32-битной системе максимальный объемaddressable memory
для любого данного процесса составляет 4 ГБ. Вполне возможно, чтоOS
резервирует некоторые изaddress space
дляkernel
( 1 ГБ), что может объяснить, почему вы достигаете предела, составляющего около 3 ГБ.
учитывая ваши комментарии ниже, вы ограничены в использовании 32-битной ОС, есть некоторые дополнительные вещи, которые вы можете попробовать, я не дал их в комментариях, так как я просто не могу легко форматировать вещи, пространство типов довольно ограничено
Увеличивать
swap
пространство: в 32-разрядной системе увеличение пространства подкачки может обеспечить дополнительную виртуальную память. Вы можете настроить размер пространства подкачки, изменив файл конфигурации /etc/dphys-swapfile
на Raspberry Pi, а затем перезапустите службу подкачки. нет никакой гарантии, что это сработает, но, учитывая короткие решения, попробуйтеРазделение вычислений. Если ваши вычисления включают в себя большие
datasets
или операции с интенсивным использованием памяти, рассмотрите возможность разделения задачи на более мелкие, управляемые части. Обрабатывайте данные небольшими порциями или пакетами, выполняйте вычисления постепенно или используйте такие методы, как потоковая передача или отображение файлов в памяти, чтобы уменьшить требования к памяти в любой момент времени.Рассмотрите альтернативные библиотеки: если
NumPy
слишком требовательна к памяти для вашей 32-битной системы, вы можете изучить альтернативные библиотеки, предлагающие аналогичную функциональность, но с меньшими требованиями к памяти. Например, вы можете рассмотреть возможность использованияPandas
с меньшими наборами данных или изучением специализированных библиотек для конкретных задач.raspberry Pi kernel
являетсяopen source
и может бытьrecompiled
где вам нужно будет внести изменения в файл конфигурации ядра(/usr/src/linux/.config)
а затем перекомпилировать ядро. В частности, вы должны изменить значениеCONFIG_OVERCOMMIT_MEMORY
вариант желаемой настройки. Установка его наCONFIG_OVERCOMMIT_MEMORY=2
позволит неограниченное перераспределение памяти.