2014-12-15 4 views
10

Sto elaborando alcuni dati ascii, eseguo alcune operazioni e poi scrivo di nuovo su un altro file (lavoro eseguito da post_processing_0.main, senza restituire nulla). Voglio parallelizzare il codice con il modulo multiprocessing, vedere il seguente frammento di codice:map_async vs apply_async: cosa dovrei usare in questo caso

from multiprocessing import Pool 
import post_processing_0 

def chunks(lst,n): 
    return [ lst[i::n] for i in xrange(n) ] 

def main(): 
    pool = Pool(processes=proc_num) 
    P={} 
    for i in range(0,proc_num): 
     P['process_'+str(i)]=pool.apply_async(post_processing_0.main, [split_list[i]]) 
    pool.close() 
    pool.join() 


proc_num=8 
timesteps=100 
list_to_do=range(0,timesteps) 
split_list=chunks(list_to_do,proc_num) 

main() 

ho letto la differenza tra mappa e asincrono, ma I don t capisco molto bene. La mia applicazione del modulo di multiprocessing è corretta?

In questo caso, dovrei usare map_async o apply_async? E perché?

Edit:

non credo che questo è un duplicato della domanda Python multiprocessing.Pool: when to use apply, apply_async or map?. Nella domanda, la risposta si concentra sull'ordine del risultato che può essere ottenuto utilizzando le due funzioni. Qui sto chiedendo: qual è la differenza quando non viene restituito nulla?

+0

possibile duplicato di [Python multiprocessing.Pool: quando utilizzare apply, applicare \ _async o map?] (Http://stackoverflow.com/questions/8533318/python-multiprocessing-pool-when-to-use-apply -apply-async-or-map) – user4815162342

+1

Ho letto quella domanda, ma non chiarisce i miei dubbi. Sto ponendo una domanda più rigida: qual è la differenza in questo caso, in cui non viene restituito alcun risultato dalla funzione parallelizzata? – Pierpaolo

risposta

12

Suggerirei map_async per tre motivi:

  1. È più pulito alla ricerca di codice. Questo:

    pool = Pool(processes=proc_num) 
    async_result = pool.map_async(post_processing_0.main, split_list) 
    pool.close() 
    pool.join() 
    

    sembra più bello di questo:

    pool = Pool(processes=proc_num) 
    P={} 
    for i in range(0,proc_num): 
        P['process_'+str(i)]=pool.apply_async(post_processing_0.main, [split_list[i]]) 
    pool.close() 
    pool.join() 
    
  2. Con apply_async, se si verifica un'eccezione all'interno di post_processing_0.main, non si sa su di esso a meno che non si chiama esplicitamente P['process_x'].get() sulla mancanza di oggetto AsyncResult , che richiederebbe l'iterazione su tutto il P. Con map_async verrà sollevata l'eccezione se si chiama async_result.get() - nessuna iterazione richiesta.

  3. map_async ha una funzionalità di chunking incorporata, che renderà il vostro codice notevolmente migliore se split_list è molto grande.

A parte questo, il comportamento è praticamente lo stesso se non ti interessa dei risultati.

8

apply_async invia un singolo lavoro al pool. map_async invia più lavori chiamando la stessa funzione con argomenti diversi. Il primo prende una funzione più una lista di argomenti; il secondo prende una funzione più iterabile (cioè la sequenza) che rappresenta gli argomenti. map_async può chiamare solo funzioni unarie (cioè funzioni che accettano un argomento).

Nel tuo caso, potrebbe essere meglio ristrutturare leggermente il codice per mettere tutti gli argomenti in un unico elenco e chiamare semplicemente map_async una volta con quella lista.

+0

Quindi, se consideriamo 4 processi e 16 file per il postelaborazione, la mappa "creerà" 16 istanze che verranno eseguite tutte nello stesso momento? – Pierpaolo

+0

Vuoi dire che il pool ha dimensione 4 e l'elenco degli argomenti ha dimensione 16? In tal caso, verranno eseguiti solo 4 alla volta; quando il primo termina, inizia il quinto, ecc. –

+0

Ok! Quindi capisco che non ci sono differenze (a parte la modifica del codice). È corretto? – Pierpaolo