Utilizzo della memoria Python di array numpy


156

Sto usando Python per analizzare alcuni file di grandi dimensioni e sto incontrando problemi di memoria, quindi sto usando sys.getsizeof () per cercare di tenere traccia dell'uso, ma il suo comportamento con array intorpiditi è bizzarro. Ecco un esempio che coinvolge una mappa di albedos che devo aprire:

>>> 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

Bene, i dati sono ancora lì, ma la dimensione dell'oggetto, una mappa di 3600x7200 pixel, è passata da ~ 200 Mb a 80 byte. Mi piacerebbe sperare che i miei problemi di memoria siano finiti e convertire tutto in array intorpiditi, ma sento che questo comportamento, se vero, violerebbe in qualche modo una legge della teoria dell'informazione o della termodinamica, o qualcosa del genere, quindi sono propenso a credere che getsizeof () non funziona con array intorpiditi. Qualche idea?


8
Dai documenti in poi sys.getsizeof: "Restituisce la dimensione di un oggetto in byte. L'oggetto può essere qualsiasi tipo di oggetto. Tutti gli oggetti incorporati restituiranno risultati corretti, ma ciò non deve valere per le estensioni di terze parti così com'è specifica dell'implementazione. Viene presa in considerazione solo il consumo di memoria direttamente attribuito all'oggetto, non il consumo di memoria degli oggetti a cui fa riferimento. "
Joel Cornett,

1
Questo rende getsizeofun indicatore inaffidabile del consumo di memoria, specialmente per le estensioni di terze parti.
Joel Cornett,

13
Fondamentalmente, il problema qui è che resizesta restituendo un view, non un nuovo array. Stai ottenendo le dimensioni della vista, non i dati effettivi.
mgilson,

A tal fine, sys.getsizeof(albedo.base)darà la dimensione della non vista.
Eric

Risposte:


236

È possibile utilizzare array.nbytesper matrici intorpidite, ad esempio:

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

È sys.getsizeof (a), dopo aver fatto import sys.
Eddys,

2
b.__sizeof__()è equivalente asys.getsizeof(b)
palash il

1
round(getsizeof(a) / 1024 / 1024,2)per ottenere MB
gies0r

13

Il campo nbyte ti darà la dimensione in byte di tutti gli elementi dell'array in un numpy.array:

size_in_bytes = my_numpy_array.nbytes

Si noti che questo non misura "attributi non element dell'oggetto della matrice", quindi la dimensione effettiva in byte può essere maggiore di qualche byte.


Questa risposta crea ancora un array, quindi penso che intendi "senza la necessità di convertire da un elenco a un array". Anche se è vero che la risposta di GWW crea prima un elenco e poi lo converte in un array, questo è accanto al punto, poiché l'OP ha già un array ... Il punto è come ottenere le dimensioni di un array intorpidito, quindi non è fondamentale come hai ottenuto l'array in primo luogo. Si potrebbe allo stesso modo criticare questa risposta dicendo che rimodella un array esistente.
Moot

Ciao @Moot, grazie per il commento. La domanda è su come ottenere la dimensione in byte di un array. Mentre è vero che il mio frammento crea prima un array, è solo allo scopo di avere un esempio completo che può essere eseguito. Modificherò la mia risposta per sottolineare questo.
El Marce,

1

Nel notebook pitone spesso mi desidera filtrare 'penzoloni' numpy.ndarray's, in particolare quelli che sono memorizzati in _1, _2ecc che non sono mai veramente destinata a rimanere in vita.

Uso questo codice per ottenere un elenco di tutti e le loro dimensioni.

Non sono sicuro se locals()o globals()è meglio qui.

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)))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.