2013-06-06 11 views
5

Mi chiedo quali sono i compromessi tra la lettura dei file in sequenza e in parallelo.Sequenziale o parallelo: qual è il modo corretto di leggere più file in python?

Diciamo che ho un file di milioni di megabyte che vorrei elaborare, ma non abbastanza memoria da contenere tutti in una volta. Per elaborare questi in sequenza, non posso fare:

results = [do_something(os.path.join(files, f)) for f in os.listdir(files)] 

Oppure posso farlo in parallelo:

paths = [os.path.join(files, f) for f in os.listdir(files)] 
p = multiprocessing.Pool() 
try: 
    results = p.map(do_something, paths) 
    p.close() 
    p.join() 
except KeyboardInterrupt: 
    p.terminate() 

In generale sono stato ammonito contro l'esecuzione parallela di I/O perché la lettura del disco è abbastanza casuale lento. Ma in questo caso è parallela la strada da percorrere? O forse qualche strategia mista?

Inoltre, noto che la versione parallela conserva la struttura della directory; vale a dire, l'output è nell'ordine corretto. Significa che lo sta facendo in modo sequenziale o Python è solo gentile? Modifica: Blender ha risolto questa seconda domanda. Grazie, Blender!

Grazie per l'aiuto.

+4

'p.map' restituisce le cose in ordine. Potresti voler vedere 'p.map_async' o' p.imap_unordered' – Blender

+0

dipende da cosa fa qualcosa_ – yaccz

+0

Puoi presumere che do_something sia una funzione piuttosto costosa che analizza il contenuto del file. – rhombidodecahedron

risposta

2

In parte dipende dal tipo di supporto di memorizzazione su cui si trovano. A causa delle attività di ricerca, un disco rigido convenzionale si muoverà quasi completamente. Un SSD, OTOH, è molto meno suscettibile alle letture casuali (anche se non è del tutto inalterato).

Anche se si dispone di un SSD, è possibile che si verifichi un punto di ritorni decrescenti, anche se la dimensione del pool predefinita è probabilmente soddisfacente e si può persino scoprire che lo sweet-spot è molto più alto di cpu_count(). Ci sono troppi fattori per fare previsioni, quindi dovresti provare diverse dimensioni del pool.

2

L'elaborazione parallela sarà danneggiata dal disco I/O se si dispone di più accessi al disco per file. Tuttavia, se si sta eseguendo un'elaborazione abbastanza piccola in do_something, potrebbe non valere l'elaborazione necessaria per il cambio di contesto che si verificherà nel pool di thread. Dal momento che dici che lo do_something è molto costoso, probabilmente vale la pena processarlo in parallelo.

Inoltre, è possibile ridurre a icona il disco I/O se si leggono i file interamente in memoria una volta sola, leggendo il file riga per riga. Ovviamente ciò richiederà più memoria, ma probabilmente ridurrà significativamente il tempo di elaborazione.

Problemi correlati