2011-12-20 9 views
9

Qualcuno può consigliare un'alternativa all'importazione di un paio di GB di dati numerici (in formato .mx) da un elenco di 60 file .mx, ciascuno di circa 650 MByte?Importazione dati enorme più rapida di Get ["raggedmatrix.mx"]?

Il - troppo grande per postare qui - problema di ricerca coinvolto semplici operazioni statistiche con doppio GB di dati (circa 34) di RAM disponibile (16). Per gestire il problema delle dimensioni dei dati, ho semplicemente diviso le cose e ho utilizzato una strategia Ottieni/Cancella per fare i conti.

Funziona, ma chiamando Get["bigfile.mx"] richiede parecchio tempo, quindi mi chiedevo se sarebbe più veloce da utilizzare BLOB o qualsiasi altra cosa con PostgreSQL o MySQL o qualsiasi cosa la gente di database utilizzare per GB di dati numerici.

Quindi la mia domanda è davvero: Qual è il modo più efficiente per gestire importazioni di serie di dati veramente grandi in Mathematica?

Non l'ho ancora provato, ma penso che SQLImport da DataBaseLink sarà più lento di Get["bigfile.mx"].

Qualcuno ha qualche esperienza da condividere?

(Scusate se questa non è una domanda di programmazione molto specifica, ma mi aiuterebbe davvero a passare a quella ricerca dispendiosa in termini di tempo che è la migliore delle 137 possibilità per-contrastare-un-problema-in-Mathematica).

+1

[Questo aiuto] (http://stackoverflow.com/q/7525782/616736)? Un'altra [domanda correlata] (http://stackoverflow.com/q/8247005/616736). – abcd

+0

@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

+0

@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

risposta

1

Credo che i due approcci migliori sono o:

1) utilizzare Get sul file * .MX,

2) o leggere in quei dati e salvarlo in qualche formato binario per il quale si scrive un codice LibraryLink e poi leggere il materiale tramite quello. Questo, ovviamente, ha lo svantaggio di dover convertire i tuoi contenuti MX. Ma forse questa è un'opzione.

In genere Get con i file MX è piuttosto veloce.

Assicurati che questo non sia un problema di scambio?

Edit 1: È quindi possibile utilizzare anche scrivere in un convertitore di importazione: tutorial/DevelopingAnImportConverter

+0

Non si tratta di un problema di scambio. Il problema è che ho più dati che nella RAM, quindi devo leggere in sequenza parti dei dati e questo viene fatto più volte, quindi se ci vuole mezzo minuto per leggere in un file MX è evidente. Le cose funzionano *, ha solo bisogno di più di un giorno di tempo CPU tutto (c'è un ciclo di ottimizzazione esterno), quindi stavo pensando a come accelerare le cose. –

+0

Posso leggere in un blocco di dati con il codice LibraryLink e scambiarlo su disco per comando? In questo momento ho bisogno di ottenere/cancellare lo stesso file MX più volte e fondamentalmente voglio accelerarlo. –

+0

Non l'ho mai fatto, quindi sono un po 'cauto, ma penso che dovrebbe essere possibile. –

3

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

+0

Hai provato la mia funzione 'dynamicPartition' (o solo la' core' dynP') nel post della borsa? Credo che dovrebbe essere un po 'più veloce quello che hai proposto. Se lo è, includerai un link? –

+0

@ Mr.Wizard Il mio punto qui è stato semplicemente quello di mostrare che l'archiviazione dei dati in un formato flat e il partizionamento nel kernel non aggiungerà un notevole overhead (non per trovare il modo migliore per partizionare). Link aggiunto, ovviamente. – Szabolcs

+0

Ovviamente hai ragione. Forse un link non è appropriato. –

Problemi correlati