Penggunaan memori python dari array numpy


156

Saya menggunakan python untuk menganalisis beberapa file besar dan saya mengalami masalah memori, jadi saya telah menggunakan sys.getsizeof () untuk mencoba dan melacak penggunaan, tetapi perilakunya dengan array numpy adalah aneh. Berikut ini contoh yang melibatkan peta albedo yang harus saya buka:

>>> import numpy as np
>>> import struct
>>> from sys import getsizeof
>>> f = open('Albedo_map.assoc', 'rb')
>>> getsizeof(f)
144
>>> albedo = struct.unpack('%df' % (7200*3600), f.read(7200*3600*4))
>>> getsizeof(albedo)
207360056
>>> albedo = np.array(albedo).reshape(3600,7200)
>>> getsizeof(albedo)
80

Yah data masih di sana, tetapi ukuran objek, peta 3600x7200 piksel, telah berubah dari ~ 200 Mb menjadi 80 byte. Saya ingin berharap masalah ingatan saya selesai dan hanya mengubah segalanya menjadi array numpy, tetapi saya merasa bahwa perilaku ini, jika benar, dalam beberapa cara akan melanggar beberapa teori teori informasi atau termodinamika, atau sesuatu, jadi saya cenderung percaya bahwa getsizeof () tidak berfungsi dengan array numpy. Ada ide?


8
Dari dokumen pada sys.getsizeof: "Kembalikan ukuran objek dalam byte. Objek tersebut dapat berupa jenis objek apa pun. Semua objek bawaan akan mengembalikan hasil yang benar, tetapi ini tidak harus berlaku untuk ekstensi pihak ketiga seperti itu implementasi spesifik. Hanya konsumsi memori yang secara langsung dikaitkan dengan objek dipertanggungjawabkan, bukan konsumsi memori objek yang dimaksud. "
Joel Cornett

1
Ini membuat getsizeofindikator konsumsi memori tidak dapat diandalkan, terutama untuk ekstensi pihak ke-3.
Joel Cornett

13
Pada dasarnya, masalah di sini resizeadalah mengembalikan a view, bukan array baru. Anda mendapatkan ukuran tampilan, bukan data aktual.
mgilson

Untuk itu, sys.getsizeof(albedo.base)akan memberikan ukuran non-view.
Eric

Jawaban:


236

Anda dapat menggunakan array.nbytesuntuk array numpy, misalnya:

>>> import numpy as np
>>> from sys import getsizeof
>>> a = [0] * 1024
>>> b = np.array(a)
>>> getsizeof(a)
8264
>>> b.nbytes
8192

Ini sys.getsizeof (a), setelah melakukan impor sys.
eddys

2
b.__sizeof__()setara dengansys.getsizeof(b)
palash

1
round(getsizeof(a) / 1024 / 1024,2)untuk mendapatkan MB
gies0r

13

Field nbytes akan memberi Anda ukuran dalam byte dari semua elemen array dalam numpy.array:

size_in_bytes = my_numpy_array.nbytes

Perhatikan bahwa ini tidak mengukur "atribut non-elemen objek array" sehingga ukuran sebenarnya dalam byte bisa beberapa byte lebih besar dari ini.


Jawaban ini masih membuat array, jadi saya pikir maksud Anda "tanpa perlu mengkonversi dari daftar ke array". Meskipun benar bahwa jawaban GWW pertama-tama membuat daftar dan kemudian mengubahnya menjadi sebuah array, itu intinya, karena OP sudah memiliki sebuah array ... Intinya adalah bagaimana mendapatkan ukuran array yang numpy, jadi bukan kritis bagaimana Anda mendapatkan array di tempat pertama. Orang juga bisa mengkritik jawaban ini dengan mengatakan bahwa itu membentuk kembali array yang ada.
Moot

Halo @Moot, terima kasih atas komentarnya. Pertanyaannya adalah tentang bagaimana cara mendapatkan ukuran dalam byte array. Memang benar bahwa cuplikan saya pertama kali menciptakan sebuah array, itu hanya untuk tujuan memiliki contoh lengkap yang dapat dieksekusi. Saya akan mengedit jawaban saya untuk menekankan hal ini.
El Marce

1

Di notebook python saya sering ingin menyaring 'menggantung' numpy.ndarray's, khususnya orang-orang yang disimpan dalam _1, _2, dll yang tidak pernah benar-benar dimaksudkan untuk tetap hidup.

Saya menggunakan kode ini untuk mendapatkan daftar semuanya dan ukurannya.

Tidak yakin apakah locals()atau globals()lebih baik di sini.

import sys
import numpy
from humanize import naturalsize

for size, name in sorted(
    (value.nbytes, name)
    for name, value in locals().items()
    if isinstance(value, numpy.ndarray)):
  print("{:>30}: {:>8}".format(name, naturalsize(size)))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.