Ho alcuni file di grandi dimensioni (anche gzip circa 10 GB), che contengono un'intestazione ASCII e quindi in linea di principio numpy.recarrays di circa 3 MB ciascuno, li chiamiamo "eventi". Il mio primo approccio si presentava così:numpy.fromfile efficiente su file zippati?
f = gzip.GzipFile(filename)
f.read(10000) # fixed length ascii header
event_dtype = np.dtype([
('Id', '>u4'), # simplified
('UnixTimeUTC', '>u4', 2),
('Data', '>i2', (1600,1024))
])
event = np.fromfile(f, dtype = event_dtype, count=1)
Tuttavia, questo non è possibile, dal momento che np.fromfile ha bisogno di un oggetto file vero e proprio, perché rende davvero chiamate di basso livello (trovato un biglietto piuttosto vecchio https://github.com/numpy/numpy/issues/1103).
Quindi, come ho capito che devo fare in questo modo:
s = f.read(event_dtype.itemsize)
event = np.fromstring(s, dtype=event_dtype, count=1)
E sì, funziona! Ma non è terribilmente inefficiente? Non sono assegnati i mem e vengono raccolti i rifiuti per ogni evento? Sul mio laptop raggiungo qualcosa come 16 eventi/s, ad esempio ~ 50MB/s
Mi chiedo se qualcuno conosce un modo intelligente, di assegnare il mem una volta e poi lasciare che numpy legga direttamente in quel mem.
Btw. Sono un fisico, quindi ... beh, sono ancora un principiante in questo business.
Il tempo impiegato dall'I/O è simile a * migliaia * di volte più grande del tempo impiegato per allocare/deallocare quella stringa. Dovresti profilare il codice per vedere dove si trova il collo di bottiglia e poi ottimizzarlo ... indovinare dove si trova il collo di bottiglia è brutto, anche di più se non sei abituato a programmare in modo efficiente. – Bakuriu
Finché stai bene con gli array di sola lettura, potresti usare 'numpy.frombuffer' per evitare di duplicare la memoria e usare semplicemente la stringa come buffer di memoria. –
@Bakariu, grazie per il fraseggio chiaro che. Non ho esperienza con il codice di profilazione. E 'bello saperlo, quella supposizione è cattiva. –