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позволит неограниченное перераспределение памяти.

Другие вопросы по тегам