2013-10-14 16 views
6

Per memorizzare una matrice grande su disco uso numpy.memmap.Moltiplicazione grande matrice numpy efficiente

Ecco un codice di esempio per testare grande moltiplicazione di matrici:

import numpy as np 
import time 

rows= 10000 # it can be large for example 1kk 
cols= 1000 

#create some data in memory 
data = np.arange(rows*cols, dtype='float32') 
data.resize((rows,cols)) 

#create file on disk 
fp0 = np.memmap('C:/data_0', dtype='float32', mode='w+', shape=(rows,cols)) 
fp1 = np.memmap('C:/data_1', dtype='float32', mode='w+', shape=(rows,cols)) 

fp0[:]=data[:] 
fp1[:]=data[:] 

#matrix transpose test 
tr = np.memmap('C:/data_tr', dtype='float32', mode='w+', shape=(cols,rows)) 
tr= np.transpose(fp1) #memory consumption? 
print fp1.shape 
print tr.shape 

res = np.memmap('C:/data_res', dtype='float32', mode='w+', shape=(rows,rows)) 
t0 = time.time() 
# redifinition ? res= np.dot(fp0,tr) #takes 342 seconds on my machine, if I multiplicate matrices in RAM it takes 345 seconds (I thinks it's a strange result) 
res[:]= np.dot(fp0,tr) # assignment ? 
print res.shape 
print (time.time() - t0) 

Quindi le mie domande sono:

  1. Come limitare consumtion memoria del aplication che sta usando questa procedura per un certo valore, per esempio a 100 Mb (o 1 Gb o qualcos'altro). Inoltre non capisco come stimare il consumo di memoria della procedura (penso che la memoria viene allocata solo quando viene creata la variabile "dati", ma quanta memoria utilizzata quando si usano i file memmap?)
  2. Forse c'è qualche soluzione ottimale per la moltiplicazione di grandi matrici memorizzate su disco? Ad esempio, forse i dati non sono memorizzati in modo ottimale su disco o letti dal disco, non correttamente memorizzati, e anche i prodotti a punti usano solo un core. Forse dovrei usare qualcosa come PyTables?

Inoltre, sono interessato agli algoritmi di risoluzione del sistema di equazioni lineari (SVD e altri) con utilizzo limitato della memoria. Forse questo algoritmo ha chiamato fuori dal core o iterativo e penso che ci sia qualche analogia come il disco rigido < -> ram, gpu ram < -> cpu ram, cpu ram < -> cpu cache.

Anche here Ho trovato alcune informazioni sulla moltiplicazione della matrice in PyTables.

Inoltre ho trovato this in R ma ne ho bisogno per Python o Matlab.

+0

"Come limitare il consumo di memoria dell'applicazione che utilizza questa procedura su un valore ad esempio a 100 Mb" Vuoi dire che se l'applicazione tenta di utilizzare più memoria dovrebbe fallire? Usare 'psutil.set_rlimit' è facile, ma AFAIK funziona solo su linux. – Bakuriu

+0

No, voglio dire che l'applicazione deve funzionare normalmente ma usare meno della memoria dichiarata (generalmente parlando sarà più lento con meno memoria, ma è utile quando vogliamo limitare l'utilizzo della memoria dell'applicazione o se non abbiamo abbastanza memoria per adattarsi intera matrice). E io lavoro su Windows. – mrgloom

+0

La riga 'res' non ha senso (e res è l'array più grande ...). Rileggere la docstring di 'np.dot', troverai qualcosa di utile ... – seberg

risposta

1

Considerare l'utilizzo NumExpr per la lavorazione: https://github.com/pydata/numexpr

... internamente, NumExpr impiega la propria macchina virtuale vettorizzati che è stato progettato intorno ad una strategia di chunked lettura, al fine di operare in modo efficiente su blocchi in modo ottimale dimensioni di dati in memoria. Può facilmente battere le operazioni NumPy se sintonizzato correttamente.

NumExpr può coprire il n. 2 nella suddivisione del problema. Se si indirizza # 1 utilizzando un formato binario streamable, è possibile poi la chunked lettura approccio durante il caricamento dei file di dati - in questo modo:

with open('path/to/your-data.bin', 'rb') as binary: 
     while True: 
      chunk = binary.read(4096) # or what have you 
      if not chunk: 
       break 

Se questo è troppo di basso livello per te, ti consiglierei guarda la libreria HDF5 e il formato: http://www.h5py.org - è la soluzione migliore per la serializzazione binaria di strutture basate su NumPy che io conosca. Il modulo h5py supporta compressione, lettura chunked, dtypes, metadati ... è il nome.

Buona fortuna!

+0

Non riesco a capire dove può essere utilizzato numexpr nella moltiplicazione della matrice, può la tua risposta di espansione e fornire un esempio di utilizzo? Sì, so di hdf5 e di pytables ma numpy.memmap è più comodo perché può essere usato come al solito array numpy. – mrgloom

+0

'numpy.memmap' è un'operazione tutto o niente, sì? ... Suggerivo hdf5 in quanto supporta il chunking e lo streaming I/O: http://www.hdfgroup.org/HDF5/doc/Advanced/Chunking/ index.html - mentre il semplice caricamento degli stessi dati con HDF5 potrebbe essere più lento dei file mappati in memoria, eseguire una lettura chunk su un ciclo di elaborazione basato su un blocco potrebbe essere più efficiente nel modo che si sta cercando. – fish2000

+0

Per quanto riguarda NumExpr, non so se offra un operatore di prodotti dot ma so che ti darà operazioni di visualizzazione più veloci - se dovessi ripristinare i tuoi array con NumExpr, potresti non aver bisogno ad es. la trasposizione che consuma la memoria. – fish2000

3

Dask.array fornisce un'interfaccia numpy a grandi array su disco che utilizzano algoritmi bloccati e pianificazione delle attività. Può facilmente fare moltiplicazioni matriciali fuori dal core e altre operazioni di numpy simple-ish.

L'algebra lineare bloccata è più difficile e si potrebbe voler controllare alcuni dei lavori accademici su questo argomento. Dask supporta fatture QR e SVD su matrici alte e sottili.

Indipendentemente dagli array di grandi dimensioni, si vogliono veramente algoritmi bloccati, non attraversamenti ingenui che colpiranno il disco in modi spiacevoli.