모양 및 데이터 유형으로 배열을 할당 할 수 없습니다.


116

MacOS에서 동일한 문제가 발생하지 않는 동안 Ubuntu 18에서 numpy에 거대한 배열을 할당하는 데 문제가 있습니다.

모양 (156816, 36, 53806) 이 있는 numpy 배열에 메모리를 할당하려고합니다.

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

Ubuntu OS에서 오류가 발생하는 동안

>>> 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배열에 필요한 전체 메모리를 실제로 할당해서는 안되는 어딘가에서 읽었 지만 0이 아닌 요소에만 해당됩니다. Ubuntu 컴퓨터에는 64GB의 메모리가 있지만 MacBook Pro에는 16GB 만 있습니다.

버전 :

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

추신 : Google Colab에서도 실패했습니다.


1
메모리에서 실행중인 다른 프로세스가 있습니까?
BlueRine S

아니, 내가 노력 top하고 free -m무료 더 MEM의 60기가바이트 밀어 경우, 그 명령을
마틴 Brisiak

흠. 기묘한. 그렇게 많은 메모리를 차지해서는 안됩니다. Macos에서 얼마나 많은 메모리를 차지했습니까?
BlueRine S

1
그럴 것 같지는 않지만 Ubuntu에서 32 비트 Python 인터프리터를 실행하지 않습니까?
jdehesa

1
np.zerossparse행렬을 만들지 않습니다 . 0을 채우는 데 지연이있을 수 있습니다. 그러나 참조 stackoverflow.com/q/27464039
hpaulj

답변:


116

이는 시스템의 오버 커밋 처리 모드 때문일 수 있습니다 .

기본 모드에서는 0,

휴리스틱 오버 커밋 처리. 주소 공간의 명백한 오버 커밋은 거부됩니다. 일반적인 시스템에 사용됩니다. 이는 스왑 사용량을 줄이기 위해 오버 커밋을 허용하면서 심각한 와일드 할당 실패를 보장합니다. 루트는이 모드에서 약간 더 많은 메모리를 할당 할 수 있습니다. 이것이 기본값입니다.

사용되는 정확한 추론이 잘되지 않습니다 여기에서 설명하지만,이 더에 대한 설명 리눅스 이상 발견 커밋이 페이지에 .

다음을 실행하여 현재 오버 커밋 모드를 확인할 수 있습니다.

$ cat /proc/sys/vm/overcommit_memory
0

이 경우에는

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

~ 282GB이며 커널은 분명히 많은 물리적 페이지를 여기에 커밋 할 수있는 방법이 없으며 할당을 거부합니다.

(루트로) 실행하는 경우 :

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

이렇게하면 "항상 오버 커밋"모드가 활성화되고 실제로 시스템은 크기에 관계없이 할당을 수행 할 수 있습니다 (적어도 64 비트 메모리 주소 지정 내에서).

32GB RAM이 장착 된 컴퓨터에서 직접 테스트했습니다. 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 "주의"경고의 정확한 의미는 무엇입니까? 즉. GTX 1080 GPU를 사용하는 Ubuntu 18 서버에서 문제가 발생하는 최악의 시나리오는 무엇입니까?
mLstudent33

1
@ mLstudent33 하나는 자체 메모리가있는 GPU와는 아무런 관련이 없습니다. 내 말은 여전히 ​​메모리를 채울 수 있다는 것입니다. 메모리의 일부 페이지에 쓸 때마다 해당 페이지 (일반적으로 4k 바이트)가 실제 메모리에 커밋되어야합니다. 따라서 최악의 시나리오는 메모리가 부족한 것입니다.
Iguananaut

1
이 변경 사항이 즉시 적용됩니까? 아니면 쉘이나 시스템 자체를 다시 시작해야합니까?
dumbledad

2
즉시 적용되지만 추가 조치 없이는 재부팅 이후에도 지속되지 않습니다. /proc/sys배포에서 설정 을 유지하는 가장 좋은 방법에 대한 다른 질문을 검색 하십시오.
Iguananaut

53

나는 Window에서 이와 동일한 문제가 있었고이 솔루션을 발견했습니다. 따라서 누군가가 Windows 에서이 문제를 발견하면 나에게도 메모리 초과 할당 문제이기 때문에 페이지 파일 크기 를 늘리는 것이 해결책이었습니다 .

윈도우 8

  1. 키보드에서 WindowsKey + X를 누른 다음 팝업 메뉴에서 시스템을 클릭합니다.
  2. 고급 시스템 설정을 탭하거나 클릭합니다. 관리자 암호를 입력하거나 선택을 확인하라는 메시지가 표시 될 수 있습니다.
  3. 고급 탭의 성능에서 설정을 탭하거나 클릭합니다.
  4. 고급 탭을 탭하거나 클릭 한 다음 가상 메모리에서 변경을 탭하거나 클릭합니다.
  5. 모든 드라이브의 페이징 파일 크기 자동 관리 확인란을 선택 취소합니다.
  6. 드라이브 [볼륨 레이블]에서 변경할 페이징 파일이있는 드라이브를 탭하거나 클릭합니다.
  7. 사용자 지정 크기를 탭하거나 클릭하고 초기 크기 (MB) 또는 최대 크기 (MB) 상자에 새 크기 (MB)를 입력하고 설정을 탭하거나 클릭 한 다음 확인을 탭하거나 클릭합니다.
  8. 시스템 재부팅

윈도우 10

  1. Windows 키 누르기
  2. 유형 SystemPropertiesAdvanced
  3. 관리자 권한으로 실행을 클릭하십시오.
  4. 성능에서 설정을 클릭합니다.
  5. 고급 탭을 선택하십시오.
  6. 변경 선택 ...
  7. 모든 드라이브의 페이징 파일 크기 자동 관리를 선택 취소하십시오.
  8. 그런 다음 사용자 정의 크기를 선택하고 적절한 크기를 입력하십시오.
  9. 설정을 누른 다음 확인을 누른 다음 가상 메모리, 성능 옵션 및 시스템 속성 대화 상자를 종료합니다.
  10. 시스템 재부팅

참고 :이 예제에서는 ~ 282GB에 대해 시스템에 충분한 메모리가 없었지만 특정 경우에는 작동했습니다.

편집하다

에서 여기 페이지 파일 크기에 대한 권장 사항을 제안 :

올바른 페이지 파일 크기를 계산하는 공식이 있습니다. 초기 크기는 1.5 x 전체 시스템 메모리 양입니다. 최대 크기는 초기 크기의 3 배입니다. 따라서 4GB (1GB = 1,024MB x 4 = 4,096MB)의 메모리가 있다고 가정 해 보겠습니다. 초기 크기는 1.5 x 4,096 = 6,144MB이고 최대 크기는 3 x 6,144 = 18,432MB입니다.

여기 에서 명심해야 할 사항 :

그러나 이것은 컴퓨터에 고유 할 수있는 다른 중요한 요소 및 시스템 설정을 고려하지 않습니다. 다시 말하지만, Windows가 다른 컴퓨터에서 작동하는 임의의 공식에 의존하는 대신 사용할 것을 선택하도록합니다.

또한:

페이지 파일 크기를 늘리면 Windows에서 불안정성과 충돌을 방지하는 데 도움이 될 수 있습니다. 그러나 하드 드라이브 읽기 / 쓰기 시간은 데이터가 컴퓨터 메모리에있을 때보 다 훨씬 느립니다. 더 큰 페이지 파일이 있으면 하드 드라이브에 추가 작업이 추가되어 다른 모든 작업이 느려집니다. 페이지 파일 크기는 메모리 부족 오류가 발생한 경우에만 일시적으로 수정해야합니다. 더 나은 해결책은 컴퓨터에 더 많은 메모리를 추가하는 것입니다.


현재 어떤 사용자 지정 크기 (초기 크기 + 최대 크기) 설정이 있습니까? 나 자신을 위해 얼마를 할당해야하는지 잘 모르겠 음
Azizbro

1
@Azizbro 이제 기본값으로 돌아 갔지만 메모리 부족 오류가 사라질 때까지 값을 조정했습니다.
recurseuntilfor

나는이 일을했는데 나는 아직도 얻을MemoryError: Unable to allocate 10.3 PiB for an array with shape (38137754, 38137754) and data type float64
george.adams1

24

나는 Windows 에서도이 문제를 발견했습니다. 나를위한 해결책 은 32 비트에서 64 비트 버전의 Python 으로 전환 하는 것이 었습니다 . 실제로 32 비트 CPU와 같은 32 비트 소프트웨어는 최대 4GB 의 RAM (2 ^ 32)을 처리 할 수 ​​있습니다. 따라서 4GB 이상의 RAM이있는 경우 32 비트 버전은이를 활용할 수 없습니다.

64 비트 버전의 Python ( 다운로드 페이지에서 x86-64 로 표시된 버전 )에서는 문제가 사라졌습니다.

통역사를 입력하여 사용중인 버전을 확인할 수 있습니다. I, 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 비트 (AMD64)]는 "64 비트 Python"을 의미합니다.

참고 :이 글을 쓰는 시점 (2020 년 5 월) 현재 matplotlib는python39에서 사용할 수 없으므로 python37, 64 비트 설치를 권장합니다.

출처 :


2
통역사는 어떻게 입력합니까?
Shayan

내 문제도 해결했습니다. Pycharm 사용. 32 비트 버전을 제거하고 64 비트 버전을 다시 설치하고 프로젝트 인터프리터를 새로운 64 비트 Python으로 변경했습니다.
Jason Goal

3

필자의 경우 dtype 속성을 추가하면 배열의 dtype이 더 작은 유형 (float64에서 uint8으로)으로 변경되어 Windows (64 비트)에서 MemoryError를 발생시키지 않을만큼 배열 크기를 줄였습니다.

...에서

mask = np.zeros(edges.shape)

...에

mask = np.zeros(edges.shape,dtype='uint8')


1

데이터 유형을 더 적은 메모리 작업을 사용하는 다른 유형으로 변경하십시오. 나를 위해 데이터 유형을 numpy.uint8로 변경합니다.

data['label'] = data['label'].astype(np.uint8)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.