Ecco un'idea:
Hai detto che hai una matrice cencioso, cioè una lista di liste di diverse lunghezze . Sto assumendo numeri in virgola mobile.
Si potrebbe appiattire la matrice per ottenere un unico lungo imballate matrice 1D (utilizzare Developer`ToPackedArray
per imballare se necessario), e memorizzare gli indici di partenza delle sottoliste separatamente. Quindi ricostruire la matrice irregolare dopo che i dati sono stati importati.
Ecco una dimostrazione che all'interno di Mathematica (vale a dire dopo l'importazione), l'estrazione dei sottoliste da una grande lista appiattita è veloce.
data = RandomReal[1, 10000000];
indexes = [email protected][{1, 10000000}, 10000];
ranges = #1 ;; (#2 - 1) & @@@ Partition[indexes, 2, 1];
data[[#]] & /@ ranges; // Timing
{0.093, Null}
alternativa memorizzare una sequenza di lunghezze sottolista e utilizzare Mr.Wizard's dynamicPartition
function che fa esattamente questo. Il mio punto è che l'archiviazione dei dati in un formato flat e il partizionamento nel kernel aggiungerà un sovraccarico trascurabile.
L'importazione di matrici imballate come file MX è molto veloce. Ho solo 2 GB di memoria, quindi non posso testare file di grandi dimensioni, ma i tempi di importazione sono sempre una frazione di secondo per gli array compressi sulla mia macchina. Ciò risolverà il problema che l'importazione di dati non imballati può essere più lenta (anche se, come ho detto nei commenti sulla domanda principale, non riesco a riprodurre il tipo di lentezza estrema che menzioni).
Se BinaryReadList
sono stati veloci (non è veloce come la lettura dei file MX ora, ma sembra che it will be significantly sped up in Mathematica 9), è possibile memorizzare l'intero set di dati come un unico grande file binario, senza il bisogno di rompere in file MX separati. Poi si potrebbe importare parti rilevanti del file in questo modo:
Per prima cosa un file di test:
In[3]:= f = OpenWrite["test.bin", BinaryFormat -> True]
In[4]:= BinaryWrite[f, RandomReal[1, 80000000], "Real64"]; // Timing
Out[4]= {9.547, Null}
In[5]:= Close[f]
aprirlo:
In[6]:= f = OpenRead["test.bin", BinaryFormat -> True]
In[7]:= StreamPosition[f]
Out[7]= 0
saltare i primi 5 milioni di voci:
In[8]:= SetStreamPosition[f, 5000000*8]
Out[8]= 40000000
Leggi 5 milioni di voci:
In[9]:= BinaryReadList[f, "Real64", 5000000] // Length // Timing
Out[9]= {0.609, 5000000}
leggere tutte le restanti voci:
In[10]:= BinaryReadList[f, "Real64"] // Length // Timing
Out[10]= {7.782, 70000000}
In[11]:= Close[f]
(Per fare un confronto, Get
solito legge gli stessi dati da un file MX in meno di 1,5 secondi qui. Io sono su WinXP btw.)
EDIT Se siete disposti a spendere tempo su questo, e scrivere del codice C, un'altra idea è di creare una funzione di libreria (utilizzando Library Link) che sarà la memoria-map il file (link for Windows) e copiarlo direttamente in un oggetto MTensor
(uno MTensor
è solo un array Mathematica compatto, come si vede dal lato C del Link della libreria).
[Questo aiuto] (http://stackoverflow.com/q/7525782/616736)? Un'altra [domanda correlata] (http://stackoverflow.com/q/8247005/616736). – abcd
@yoda Si noti che Rolf sta usando MX, che è il formato binario nativo di Mathematica, e nella mia esperienza più veloce di qualsiasi altra cosa quando si usa 'Import' /' ReadList'. Non so su 'BinaryReadList' ... – Szabolcs
@Rolf ** + 1 **, domanda molto pertinente. Non ti risponde, ma sicuramente ti interesserà [in questa presentazione] (http://library.wolfram.com/infocenter/Conferences/8025/). Sembra che Mathematica 9 stia apportando miglioramenti significativi in questo settore. – Szabolcs