Невозможно выделить массив с формой и типом данных

103

У меня проблема с выделением огромных массивов в numpy в Ubuntu 18, но не с такой же проблемой в MacOS.

Я пытаюсь выделить память для массива numpy с формой (156816, 36, 53806) с

np.zeros((156816, 36, 53806), dtype='uint8')

и пока я получаю сообщение об ошибке в ОС Ubuntu

>>> import numpy as np
>>> np.zeros((156816, 36, 53806), dtype='uint8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
numpy.core._exceptions.MemoryError: Unable to allocate array with shape (156816, 36, 53806) and data type uint8

У меня не получается на MacOS:

>>> import numpy as np 
>>> np.zeros((156816, 36, 53806), dtype='uint8')
array([[[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       ...,

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]],

       [[0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        ...,
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0],
        [0, 0, 0, ..., 0, 0, 0]]], dtype=uint8)

Я где-то читал, что на np.zerosсамом деле не следует выделять всю память, необходимую для массива, а только для ненулевых элементов. Несмотря на то, что машина Ubuntu имеет 64 ГБ памяти, в то время как мой MacBook Pro имеет только 16 ГБ.

версии:

Ubuntu
os -> ubuntu mate 18
python -> 3.6.8
numpy -> 1.17.0

mac
os -> 10.14.6
python -> 3.6.4
numpy -> 1.17.0

PS: тоже не удалось на Google Colab

Мартин Брисиак
источник
1
Есть ли другие процессы, запущенные в памяти?
BlueRine S
нет, я пробовал, topи free -mте команды, где пихают 60 ГБ памяти бесплатно и больше
Мартин Бризиак
хммм. странно. Это не должно занимать столько памяти. Сколько памяти занимало на Macos?
BlueRine S
1
Маловероятно, но у вас ведь случайно не работает 32-битный интерпретатор Python в Ubuntu?
jdehesa
1
np.zerosне создает sparseматрицу. Может быть задержка с заполнением нулей. Но увидеть stackoverflow.com/q/27464039
hpaulj

Ответы:

106

Скорее всего, это связано с режимом обработки избыточной нагрузки вашей системы .

В режиме по умолчанию 0,

Эвристическая обработка переопределения. Явные чрезмерные ограничения адресного пространства отклоняются. Используется для типовой системы. Это гарантирует, что серьезный сбой при выделении ресурсов не выполняется, в то же время позволяя чрезмерное выделение ресурсов для уменьшения использования свопа. В этом режиме root может выделить немного больше памяти. Это значение по умолчанию.

Точная используемая эвристика здесь недостаточно объяснена, но в Linux она обсуждается больше, чем эвристика фиксации и на этой странице .

Вы можете проверить текущий режим перегрузки, запустив

$ cat /proc/sys/vm/overcommit_memory
0

В этом случае вы выделяете

>>> 156816 * 36 * 53806 / 1024.0**3
282.8939827680588

~ 282 ГБ, и ядро ​​говорит хорошо, очевидно, я не смогу закрепить такое количество физических страниц для этого, и оно отказывается от выделения.

Если (как root) вы запустите:

$ echo 1 > /proc/sys/vm/overcommit_memory

Это включит режим «всегда сверхкоммитировать», и вы обнаружите, что действительно система позволит вам сделать выделение независимо от того, насколько оно велико (по крайней мере, в пределах 64-битной адресации памяти).

Я сам тестировал это на машине с 32 ГБ оперативной памяти. В режиме overcommit у 0меня тоже есть MemoryError, но после его возврата 1он работает:

>>> import numpy as np
>>> a = np.zeros((156816, 36, 53806), dtype='uint8')
>>> a.nbytes
303755101056

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

Игуананавт
источник
2
Это особенность ядра Linux, поэтому в MacOS нет прямого эквивалента, хотя, возможно, что-то подобное. Я не думаю, что на Mac так же легко менять настройки ядра.
Iguananaut
1
@Iguananaut, что означает предупреждение "с осторожностью"? т.е. Каков худший сценарий, когда что-то пойдет не так на сервере Ubuntu 18 с графическим процессором GTX 1080?
mLstudent33
1
@ mLstudent33 Во-первых, это не имеет ничего общего с вашим графическим процессором, у которого есть собственная память. Все, что я имею в виду, это то, что вы все еще можете заполнить свою память - каждый раз, когда вы записываете какую-либо страницу в памяти, эта страница (обычно 4 КБ) должна быть сохранена в физической памяти. Так что в худшем случае у вас закончится память.
Iguananaut
1
Это изменение вступает в силу немедленно или нам нужно перезапустить нашу оболочку или сам компьютер?
Дамблдад,
2
Он вступает в силу немедленно, но не сохранится после перезагрузки без дополнительных мер. Поищите другие вопросы о том, как лучше всего сохранить /proc/sysнастройки в вашем дистрибутиве.
Iguananaut,
44

У меня была такая же проблема с Window, и я нашел это решение. Так что, если кто-то сталкивается с этой проблемой в Windows, решением для меня было увеличение размера файла подкачки , так как для меня это тоже была проблема с перегрузкой памяти.

Windows 8

  1. На клавиатуре нажмите WindowsKey + X, затем щелкните Система во всплывающем меню.
  2. Коснитесь или щелкните Дополнительные параметры системы. Вас могут попросить ввести пароль администратора или подтвердить ваш выбор
  3. На вкладке «Дополнительно» в разделе «Производительность» коснитесь или щелкните «Параметры».
  4. Коснитесь или щелкните вкладку Дополнительно, а затем в разделе Виртуальная память коснитесь или щелкните Изменить
  5. Снимите флажок Автоматически управлять размером файла подкачки для всех дисков.
  6. В разделе Диск [Метка тома] коснитесь или щелкните диск, содержащий файл подкачки, который нужно изменить.
  7. Коснитесь или щелкните Пользовательский размер, введите новый размер в мегабайтах в поле начальный размер (МБ) или Максимальный размер (МБ), коснитесь или щелкните Установить, а затем коснитесь или щелкните ОК
  8. Перезагрузите вашу систему

Windows 10

  1. Нажмите клавишу Windows
  2. Тип SystemPropertiesAdvanced
  3. Щелкните Запуск от имени администратора.
  4. Щелкните Настройки
  5. Выберите вкладку Advanced
  6. Выберите Изменить ...
  7. Снимите флажок Автоматически управлять размером файла подкачки для всех дисков.
  8. Затем выберите нестандартный размер и заполните соответствующий размер.
  9. Нажмите Set, затем нажмите OK, затем выйдите из диалогового окна Virtual Memory, Performance Options и System Properties.
  10. Перезагрузите вашу систему

Примечание: у меня не было достаточно памяти в моей системе для ~ 282 ГБ в этом примере, но для моего конкретного случая это сработало.

РЕДАКТИРОВАТЬ

Из здесь предложенных рекомендаций по размеру файла подкачки:

Существует формула для расчета правильного размера файла подкачки. Первоначальный размер составляет полтора (1,5) размера общей системной памяти. Максимальный размер - три (3) раза больше исходного. Допустим, у вас есть 4 ГБ (1 ГБ = 1024 МБ x 4 = 4096 МБ) памяти. Первоначальный размер будет 1,5 x 4096 = 6 144 МБ, а максимальный - 3 x 6 144 = 18 432 МБ.

Некоторые вещи , чтобы иметь в виду , от сюда :

Однако при этом не принимаются во внимание другие важные факторы и системные настройки, которые могут быть уникальными для вашего компьютера. Опять же, позвольте Windows выбирать, что использовать, вместо того, чтобы полагаться на какую-то произвольную формулу, которая работала на другом компьютере.

Также:

Увеличение размера файла подкачки может помочь предотвратить нестабильность и сбои в Windows. Однако время чтения / записи жесткого диска намного меньше, чем было бы, если бы данные были в памяти вашего компьютера. Наличие файла подкачки большего размера потребует дополнительной работы для вашего жесткого диска, в результате чего все остальное будет работать медленнее. Размер файла подкачки следует увеличивать только при возникновении ошибок нехватки памяти и только в качестве временного исправления. Лучшее решение - увеличить объем памяти компьютера.

рекурсивно
источник
какие настройки нестандартного размера (начальный размер + максимальный размер) у вас есть прямо сейчас? Не уверен, сколько выделить для себя
Азизбро
1
@Azizbro Сейчас я вернулся к значениям по умолчанию, но просто изменил значения, пока не исчезла ошибка нехватки памяти.
recurse до
23

Я столкнулся с этой проблемой и в Windows. Решением для меня был переход с 32-битной на 64-битную версию Python . Действительно, 32-разрядное программное обеспечение, такое как 32-разрядный процессор, может адресовать максимум 4 ГБ ОЗУ (2 ^ 32). Поэтому, если у вас более 4 ГБ ОЗУ, 32-разрядная версия не сможет воспользоваться ею.

С 64-битной версией Python (той, что обозначена как x86-64 на странице загрузки) проблема исчезла.

Вы можете проверить, какая у вас версия, введя интерпретатор. У меня с 64-битной версией теперь есть:, Python 3.7.5rc1 (tags/v3.7.5rc1:4082f600a5, Oct 1 2019, 20:28:14) [MSC v.1916 64 bit (AMD64)]где [MSC v.1916 64 bit (AMD64)] означает «64-битный Python».

Примечание : на момент написания этой статьи (май 2020 г.) matplotlib недоступен на python39, поэтому я рекомендую установить python37, 64 бита.

Источники:

Котчване
источник
Спасибо. С последней стабильной 64-битной версией Python (3.8.3) я также могу установить matplotlib.
Федерико Томази,
1
Как мне записаться на переводчика?
Шаян
Решил и мою проблему. Используя Pycharm. Удалена 32-битная версия, переустановлена ​​64-битная, интерпретатор проекта заменен на новый 64-битный питон.
Джейсон Гол
3

В моем случае добавление атрибута dtype изменило dtype массива на меньший тип (с float64 на uint8), уменьшив размер массива настолько, чтобы не вызывать ошибку MemoryError в Windows (64-разрядная версия).

из

mask = np.zeros(edges.shape)

к

mask = np.zeros(edges.shape,dtype='uint8')
Pragya Agrawal
источник
2

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

Антонио Морено Мартин
источник
4
Пожалуйста, обратитесь: stackoverflow.com/help/how-to-answer Хорошая попытка.
Кишан Мехта,
1

изменить тип данных на другой, который использует меньше памяти. Для меня я меняю тип данных на numpy.uint8:

data['label'] = data['label'].astype(np.uint8)
Минмин Цю
источник