Ho trovato che né le risposte di sclarke81 né di Sam Robert funzionano effettivamente, e dubito che il concetto di preallocazione si applichi a matfile
. I risultati riportati di seguito sono stati ottenuti su una CPU i7-3770 a 3,4 GHz con 16,8 GB di memoria principale, eseguendo Matlab R2013a su Linux 3.16.
Il codice
mf = matfile(fn, 'Writable', true);
mf.x(5000, 200000) = 0;
clear mf
teoricamente "alloca" 8 GB di memoria su disco, inizializzato a 0. Tuttavia, il file risultante ha una dimensione di 4726 byte e il processo richiede meno di 0,01 secondi. Posso aumentare la dimensione 10 o 100 volte e non cambia molto. Strano. Btw., Lo clear
alla fine è lì per assicurare che il file sia scritto e chiuso da Matlab.
Spesso vogliamo preallocare inizializzazione a NaN invece di 0. In questo modo il ricevuto modo
mf = matfile(fn, 'Writable', true);
mf.x = nan(5000, 200000);
clear mf
prende 11 secondi ed i risultati in un file di 57 MB. Ma come ha sottolineato il PO, questo approccio non ha senso perché prima genera l'intera matrice di 8 GB in memoria e poi la scrive, che sconfigge lo scopo di matfile
. Se la matrice si adatta alla memoria, in primo luogo non c'è motivo di conservare i dati in un file durante l'elaborazione.
Sam Roberts propone di primo allocare/inizializzare a 0 come sopra, e quindi modificare i valori NaN:
mf = matfile(fn, 'Writable', true);
mf.x(5000, 200000) = 0;
mf.x = mf.x * nan;
clear mf
Questo richiede 16 secondi, con la stessa dimensione del file risultante. Tuttavia, questo non è in alcun modo migliore dell'approccio naive di cui sopra, perché sulla terza riga l'intera matrice viene letta in memoria, moltiplicata con NaN scalare in memoria, e quindi scritta di nuovo, portando ad un consumo di memoria di picco di 8 GB. (Questo non è solo coerente con la semantica matfile
-variabili spiegato nel documentation, ma anche controllato con un monitor di utilizzo della memoria.)
sclarke81 propone di evitare invece generazione della matrice di memoria in questo modo:
mf = matfile(fn, 'Writable', true);
mf.x(1 : 5000, 1 : 200000) = nan;
clear mf
l'idea è probabilmente che solo un NaN scalare viene generato in memoria e quindi copiato in ogni elemento della matrice su disco. Tuttavia, non è quello che succede. In realtà, questo metodo sembra consumare circa 8,38 GB di memoria al picco, il 12% in più rispetto all'approccio ingenuo!
Ora più nel merito della preallocazione con matfile
. Se non si preallocare, ma riempie l'array row-wise con NaNs
mf = matfile(fn, 'Writable', true);
for i = 1 : 5000
mf.x(i, 1 : 200000) = nan(1, 200000);
end
clear mf
questo richiede 27 secondi. Ma, se uno prealloca inizializzazione a 0 e poi fila-wise sovrascrittura di NaN
mf = matfile(fn, 'Writable', true);
mf.x(5000, 200000) = 0;
for i = 1 : 5000
mf.x(i, 1 : 200000) = nan(1, 200000);
end
clear mf
ci vogliono secoli: il processo è stato solo circa il 3% finito quando ho abortito dopo 45 minuti, estrapolando a circa un giorno di runtime totale!
Il comportamento di matlab.io.MatFile
è scuro e misterioso, e sembra che al momento, solo il test approfondito porterà a un modo efficace per utilizzare questa funzione. Tuttavia, si può concludere che la preallocazione è una cattiva idea quando si tratta di matfile
.
Hmm, domanda correlata Suppongo sia se ci sia * bisogno * di preallocare in questo caso. Il solito vantaggio prestazionale sarà presumibilmente insignificante rispetto al tempo impiegato per scrivere cose sul disco ... Immagino che eviti che il file sia frammentato? – Flyto