Tidak dapat mengalokasikan larik dengan bentuk dan tipe data

116

Saya menghadapi masalah dengan mengalokasikan array besar di numpy di Ubuntu 18 sementara tidak menghadapi masalah yang sama di MacOS.

Saya mencoba mengalokasikan memori untuk array numpy dengan bentuk (156816, 36, 53806) dengan

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

dan sementara saya mendapatkan kesalahan pada OS 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

Saya tidak mendapatkannya di 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)

Saya telah membaca di suatu tempat yang np.zerosseharusnya tidak benar-benar mengalokasikan seluruh memori yang dibutuhkan untuk array, tetapi hanya untuk elemen bukan nol. Padahal mesin Ubuntu memiliki memori 64 GB, sedangkan MacBook Pro saya hanya memiliki 16 GB.

versi:

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: juga gagal di Google Colab

Martin Brisiak
sumber
1
Apakah ada proses lain yang berjalan di memori?
BlueRine S
tidak, saya mencoba topdan free -m, perintah-perintah itu di mana mendorong 60 GB mem gratis dan lebih banyak lagi
Martin Brisiak
hmmm. aneh. Seharusnya itu tidak memakan banyak memori. Berapa banyak memori yang digunakannya di Macos?
BlueRine S
1
Tidak mungkin, tetapi Anda tidak menjalankan interpreter Python 32 bit di Ubuntu, bukan?
jdehesa
1
np.zerostidak membuat sparsematriks. Mungkin ada penundaan dalam mengisi angka nol. Tetapi lihat stackoverflow.com/q/27464039
hpaulj

Jawaban:

115

Ini mungkin karena mode penanganan overcommit sistem Anda .

Dalam mode default 0,,

Penanganan overcommit heuristik. Ruang alamat yang terlalu banyak dan jelas ditolak. Digunakan untuk sistem tipikal. Ini memastikan alokasi liar yang serius gagal sementara memungkinkan overcommit untuk mengurangi penggunaan swap. root diizinkan untuk mengalokasikan sedikit lebih banyak memori dalam mode ini. Ini adalah defaultnya.

Heuristik yang tepat digunakan tidak dijelaskan dengan baik di sini, tetapi ini dibahas lebih lanjut di Linux daripada heuristik komit dan di halaman ini .

Anda dapat memeriksa mode overcommit Anda saat ini dengan menjalankan

$ cat /proc/sys/vm/overcommit_memory
0

Dalam hal ini Anda mengalokasikan

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

~ 282 GB, dan kernel mengatakan dengan baik jelas tidak ada cara saya akan dapat melakukan banyak halaman fisik untuk ini, dan menolak alokasi.

Jika (sebagai root) Anda menjalankan:

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

Ini akan mengaktifkan mode "selalu overcommit", dan Anda akan menemukan bahwa memang sistem akan memungkinkan Anda untuk membuat alokasi tidak peduli seberapa besar itu (setidaknya dalam memori 64-bit).

Saya menguji ini sendiri pada mesin dengan RAM 32 GB. Dengan mode overcommit 0saya juga mendapat MemoryError, tetapi setelah mengubahnya kembali 1berfungsi:

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

Anda kemudian dapat melanjutkan dan menulis ke lokasi mana pun dalam larik, dan sistem hanya akan mengalokasikan halaman fisik saat Anda secara eksplisit menulis ke halaman itu. Jadi, Anda dapat menggunakan ini, dengan hati-hati, untuk larik jarang.

Iguananaut
sumber
2
Ini secara khusus merupakan fitur dari kernel Linux sehingga tidak perlu ada padanan langsung di MacOS, meskipun mungkin sesuatu yang serupa. Saya tidak berpikir itu semudah di Mac untuk mengubah pengaturan kernel.
Iguananaut
1
@Iguananaut apa arti sebenarnya dari peringatan "dengan hati-hati"? yaitu. Apa skenario kasus terburuk dari sesuatu yang salah dengan ini pada server Ubuntu 18 dengan GPU GTX 1080?
mLstudent33
1
@ mLstudent33 Pertama, ini tidak ada hubungannya dengan GPU Anda, yang memiliki memorinya sendiri. Yang saya maksud adalah Anda masih dapat mengisi memori Anda - setiap kali Anda menulis ke beberapa halaman dalam memori, halaman tersebut (biasanya 4k byte) harus dimasukkan ke memori fisik. Jadi skenario kasus terburuk adalah Anda kehabisan memori.
Iguananaut
1
Apakah perubahan ini segera berlaku atau apakah kita perlu memulai ulang shell atau mesin itu sendiri?
dumbledad
2
Ini segera berlaku, tetapi tidak akan bertahan setelah reboot tanpa tindakan tambahan. Cari pertanyaan lain tentang cara terbaik untuk mempertahankan /proc/syspengaturan pada distribusi Anda.
Iguananaut
53

Saya memiliki masalah yang sama di Window's dan menemukan solusi ini. Jadi jika seseorang menemukan masalah ini di Windows, solusi bagi saya adalah meningkatkan ukuran pagefile , karena ini juga merupakan masalah komitmen berlebihan Memori bagi saya.

Windows 8

  1. Pada Keyboard Tekan WindowsKey + X lalu klik System di menu popup
  2. Ketuk atau klik Pengaturan sistem lanjutan. Anda mungkin dimintai kata sandi admin atau untuk mengonfirmasi pilihan Anda
  3. Pada tab Tingkat Lanjut, di bawah Kinerja, ketuk atau klik Pengaturan.
  4. Ketuk atau klik tab Lanjutan, lalu di bawah Memori virtual, ketuk atau klik Ubah
  5. Kosongkan kotak centang Kelola ukuran file paging untuk semua drive secara otomatis.
  6. Di bawah Drive [Volume Label], ketuk atau klik drive yang berisi file halaman yang ingin Anda ubah
  7. Ketuk atau klik Ukuran khusus, masukkan ukuran baru dalam megabyte di kotak ukuran awal (MB) atau Ukuran maksimum (MB), ketuk atau klik Atur, lalu ketuk atau klik OK
  8. Mulai ulang sistem Anda

Windows 10

  1. Tekan tombol Windows
  2. Ketik SystemPropertiesAdvanced
  3. Klik Jalankan sebagai administrator
  4. Di bawah Kinerja, klik Pengaturan
  5. Pilih tab Advanced
  6. Pilih Ubah ...
  7. Hapus centang Otomatis mengelola ukuran file paging untuk semua drive
  8. Kemudian pilih Ukuran khusus dan isi ukuran yang sesuai
  9. Tekan Set lalu tekan OK kemudian keluar dari Virtual Memory, Performance Options, dan System Properties Dialog
  10. Mulai ulang sistem Anda

Catatan: Saya tidak memiliki cukup memori di sistem saya untuk ~ 282GB dalam contoh ini, tetapi untuk kasus khusus saya ini berhasil.

EDIT

Dari sini rekomendasi yang disarankan untuk ukuran file halaman:

Ada rumus untuk menghitung ukuran pagefile yang benar. Ukuran awal adalah satu setengah (1,5) x jumlah total memori sistem. Ukuran maksimal adalah tiga (3) x ukuran awal. Jadi katakanlah Anda memiliki memori 4 GB (1 GB = 1.024 MB x 4 = 4.096 MB). Ukuran awal adalah 1,5 x 4.096 = 6.144 MB dan ukuran maksimum adalah 3 x 6.144 = 18.432 MB.

Beberapa hal yang perlu diperhatikan dari sini :

Namun, ini tidak mempertimbangkan faktor penting lain dan pengaturan sistem yang mungkin unik untuk komputer Anda. Sekali lagi, biarkan Windows memilih apa yang akan digunakan daripada mengandalkan beberapa formula arbitrer yang bekerja pada komputer lain.

Juga:

Meningkatkan ukuran file halaman dapat membantu mencegah ketidakstabilan dan crash di Windows. Namun, waktu baca / tulis hard drive jauh lebih lambat daripada jika datanya ada di memori komputer Anda. Memiliki file halaman yang lebih besar akan menambah pekerjaan ekstra untuk hard drive Anda, menyebabkan segala sesuatu berjalan lebih lambat. Ukuran file halaman seharusnya hanya ditingkatkan saat mengalami kesalahan kehabisan memori, dan hanya sebagai perbaikan sementara. Solusi yang lebih baik adalah menambahkan lebih banyak memori ke komputer.

berulang sampai
sumber
Apa setelan ukuran khusus (ukuran awal + ukuran maksimum) yang Anda miliki saat ini? Tidak yakin berapa banyak yang harus dialokasikan untuk diri saya sendiri
Azizbro
1
@Azizbro Saya telah kembali ke default sekarang tetapi hanya menyesuaikan nilai sampai kesalahan kehabisan memori menghilang.
berulang hingga
Saya telah melakukan ini dan saya masih mendapatkanMemoryError: Unable to allocate 10.3 PiB for an array with shape (38137754, 38137754) and data type float64
george.adams1
24

Saya juga menemukan masalah ini di Windows. Solusi bagi saya adalah beralih dari Python versi 32-bit ke 64-bit . Memang, perangkat lunak 32-bit, seperti CPU 32-bit, dapat memiliki ukuran maksimum 4 GB RAM (2 ^ 32). Jadi jika Anda memiliki lebih dari 4 GB RAM, versi 32-bit tidak dapat memanfaatkannya.

Dengan Python versi 64-bit (yang berlabel x86-64 di halaman unduhan), masalah ini menghilang.

Anda dapat memeriksa versi yang Anda miliki dengan memasukkan penerjemah. Saya, dengan versi 64-bit, sekarang memiliki Python 3.7.5rc1 (tags/v3.7.5rc1:4082f600a5, Oct 1 2019, 20:28:14) [MSC v.1916 64 bit (AMD64)]:, di mana [MSC v.1916 64 bit (AMD64)] berarti "64-bit Python".

Catatan : pada saat penulisan ini (Mei 2020), matplotlib tidak tersedia di python39, jadi saya merekomendasikan untuk menginstal python37, 64 bit.

Sumber:

kotchwane.dll
sumber
1
Bagaimana cara saya masuk juru bahasa?
Shayan
Memecahkan masalah saya juga. Menggunakan Pycharm. Versi 32-bit yang dihapus, yang 64-bit diinstal ulang, mengubah penafsir proyek ke python 64-bit yang baru.
Jason Goal
3

Dalam kasus saya, menambahkan atribut dtype mengubah dtype array menjadi tipe yang lebih kecil (dari float64 ke uint8), mengurangi ukuran array agar tidak membuang MemoryError di Windows (64 bit).

dari

mask = np.zeros(edges.shape)

untuk

mask = np.zeros(edges.shape,dtype='uint8')
Pragya Agrawal
sumber
1

Terkadang, kesalahan ini muncul karena kernel telah mencapai batasnya. Coba restart kernel, ulangi langkah-langkah yang diperlukan.

Antonio Moreno Martín
sumber
4
Silakan lihat: stackoverflow.com/help/how-to-answer Usaha yang bagus.
Kishan Mehta
1

ubah tipe data ke tipe lain yang menggunakan lebih sedikit memori. Bagi saya, saya mengubah tipe datanya menjadi numpy.uint8:

data['label'] = data['label'].astype(np.uint8)
Mingming Qiu
sumber