2015-05-29 7 views
7

Ho una funzione che accetta un id di un nodo come input e calcola qualcosa nel grafico (senza alterare l'oggetto grafico), quindi salva i risultati sul file system, il mio codice assomiglia a questo:Come risparmiare memoria durante l'utilizzo di Multiprocessing in Python?

... 
# graph file is being loaded 
g = loadGraph(gfile='data/graph.txt') 
# list of nodeids is being loaded 
nodeids = loadSeeds(sfile='data/seeds.txt') 

import multiprocessing as mp 
# parallel part of the code 
print ("entering the parallel part ..") 
num_workers = mp.cpu_count() # 4 on my machine 
p = mp.Pool(num_workers) 
# _myParallelFunction(nodeid) {calculate something for nodeid in g and save it into a file} 
p.map(_myParallelFunction, nodeids) 
p.close() 
... 

Il problema è quando carico il grafico in Python ci vuole molta memoria (circa 2G, è un grande grafico con in realtà migliaia di nodi), ma quando inizia a entrare nella parte parallela del codice (il parallelo l'esecuzione della funzione map) sembra che ad ogni processo sia stata data una copia separata di g e ho semplicemente esaurito la memoria sulla mia macchina (ha 6G ram e 3G swap), quindi volevo vedere che c'è un modo per dare ad ogni processo la stessa copia di g in modo che fosse richiesta solo la memoria per conservarne una copia? eventuali suggerimenti sono apprezzati e grazie in anticipo.

+0

Non ne so abbastanza per darvi una risposta solida, tuttavia un suggerimento sarebbe quello di dividere il grafico in una sezione più piccola e quindi utilizzare i processi per "dividere e conquistare" sostanzialmente. – KronoS

+1

È possibile inserire il grafico in un 'multiprocessing.Manager 'personalizzato, che consentirà a tutti i processi di utilizzare un grafico condiviso ospitato nel processo' Manager'. Tuttavia, ciò comporta una grande penalizzazione delle prestazioni quando si accede al grafico condiviso, quindi potrebbe non migliorare le prestazioni rispetto all'approccio sequenziale. – dano

+1

Stai eseguendo questo su Windows? Se stavi eseguendo questo su Linux CoW dovresti idealmente dare il via e impedire che vengano create più copie di 'nodeIDs'. Vedi questo [commento] (http://rhodesmill.org/brandon/2010/python-multiprocessing-linux-windows/#comment-160800553) e l'articolo associato – iruvar

risposta

1

Se la divisione del grafico in parti più piccole non funziona, potrebbe essere possibile trovare una soluzione utilizzando this o multiprocessing.sharedctypes, a seconda del tipo di oggetto del grafico.

1

Il commento indica che si sta elaborando un singolo nodo alla volta:

# _myParallelFunction(nodeid) {calculate something for nodeid in g and save it into a file} 

vorrei creare una funzione di generatore che restituisce un singolo nodo dal file grafico ogni volta che si chiama, e passare tale generatore per la funzione p.map() invece dell'intero elenco di nodeids.

+0

'multiprocessing.Pool.map' trasformerà il generatore in un elenco prima di elaborarlo. Devi usare 'multiprocessing.pool.imap' per evitarlo. – dano