2013-08-11 13 views
23

Sono nuovo di multiprocessing in Python e sto cercando di capire se dovrei usare Pool o Process per chiamare due funzioni asincrone. Le due funzioni che ho effettuato richiamano e analizzano le informazioni in due elenchi separati. A seconda della connessione Internet, ciascuna funzione potrebbe richiedere circa 4 secondi ciascuna. Mi rendo conto che il collo di bottiglia si trova nella connessione ISP e che il multiprocessing non lo accelera molto, ma sarebbe bello averli entrambi avviati asincroni. Inoltre, per me è una grande esperienza di apprendimento entrare nella multielaborazione di Python perché la userò più tardi.Processo o pool di multiprocessing di Python per quello che sto facendo?

Ho letto Python multiprocessing.Pool: when to use apply, apply_async or map? ed è stato utile, ma avevo ancora le mie domande.

Quindi un modo ho potuto farlo è:

Domande che ho per questa implementazione è: 1) Dal momento che unirsi a blocchi fino al completamento processo chiamando ... vuol dire questo processo p1 deve finire prima che il processo p2 venga avviato? Ho sempre capito che .join() è lo stesso di pool.apply() e pool.apply_sync(). Get() dove il processo genitore non può avviare un altro processo (attività) finché non viene completato quello corrente.

L'altra alternativa sarebbe qualcosa di simile:

def foo(): 
    pass 

def bar(): 
    pass 
pool = Pool(processes=2)    
p1 = pool.apply_async(foo) 
p1 = pool.apply_async(bar) 

Domande che ho per questa implementazione potrebbe essere: 1) Ho bisogno di un pool.close(), pool.join()? 2) Pool.map() li completerebbe tutti prima che potessi ottenere risultati? E se è così, corrono ancora asynch? 3) In che modo pool.apply_async() differisce dal fare ogni processo con pool.apply() 4) In che cosa differirebbe dalla precedente implementazione con Process?

risposta

22

I due scenari elencati hanno la stessa funzione ma in modi leggermente diversi.

Il primo scenario dalle due processi separati (li P1 e P2 chiamata) e inizia P1 e P2 esecuzione foo esecuzione bar, e quindi attende che entrambi i processi hanno terminato i loro rispettivi compiti.

Il secondo scenario inizia due processi (chiamarli Q1 e Q2) e prima inizia foo su entrambi Q1 o Q2, e poi inizia bar su entrambi Q1 o Q2. Quindi il codice attende finché non vengono restituite entrambe le chiamate di funzione.

Quindi il risultato netto è in realtà lo stesso, ma nel primo caso è garantito l'esecuzione di foo e bar su diversi processi.

Per quanto riguarda le domande specifiche che avevo su concorrenza, il metodo .join() su un Process non effettivamente bloccare fino a quando il processo è finito, ma perché hai chiamato .start() sia su P1 e P2 (nel primo scenario) prima di entrare, poi entrambi i processi verranno eseguiti in modo asincrono. L'interprete, tuttavia, attenderà fino alla fine di P1 prima di tentare di aspettare che P2 finisca.

Per le tue domande sullo scenario del pool, dovresti usare tecnicamente lo pool.close() ma in un certo senso dipende da cosa potresti aver bisogno per dopo (se va fuori dal campo di applicazione quindi non è necessario chiuderlo necessariamente).pool.map() è un tipo di animale completamente diverso, poiché distribuisce un gruppo di argomenti alla stessa funzione (in modo asincrono), attraverso i processi del pool, quindi attende fino a quando tutte le chiamate di funzione non sono state completate prima di restituire l'elenco dei risultati.

9

Dato che si stanno recuperando dati da chiamate di arricciamento, si è vincolati all'IO. In tal caso, grequests potrebbe tornare utile. Questi sono in realtà né processi né fili ma coroutine - fili leggeri. Ciò consentirebbe di inviare richieste HTTP asincroni e quindi utilizzare multiprocessing.Pool per accelerare la parte associata alla CPU.

1) Poiché i blocchi di join fino al completamento del processo di chiamata ... significa che il processo p1 deve terminare prima dell'avvio del processo p2?

Sì, p2.join() viene chiamato dopo p1.join() è tornato significa p1 ha finito.

1) Ho bisogno di un pool.close(), pool.join()

si potrebbe finire con i processi orfani senza fare close() e join() (se i processi servono indefinitamente)

2) Sarebbe pool.map() renderli tutti completi prima che potessi ottenere risultati? E se è così, corrono ancora asynch?

Vengono eseguiti in modo asincrono, ma il map() viene bloccato fino al termine di tutte le attività.

3) Come sarebbe pool.apply_async() differiscono dal fare ogni processo con pool.apply()

pool.apply() sta bloccando, in modo sostanzialmente si farebbe l'elaborazione in modo sincrono.

4) Come potrebbe questo essere diverso dal l'attuazione precedente, con processo

Le probabilità sono un lavoratore è fatto con foo prima di applicare bar così si potrebbe finire con un singolo lavoratore che fa tutto il lavoro. Inoltre, se uno dei tuoi dipendenti muore, Pool ne genera automaticamente uno nuovo (è necessario riapplicare l'attività).

Riassumendo: avrei preferito andare con Pool - è perfetto per i casi produttore-consumatore e si prende cura di tutta la logica task-distribuzione.

+1

Sei sicuro che il processo p1 debba finire prima che il processo p2 venga avviato perché join()? l'output di http://bpaste.net/show/ruHgFTAAMkN4UT2INPqu/ sembra uscito in p2 prima che finisca p1. – dman

+2

Intendevo che 'p2' sarà unito dopo che' p1' ha finito di unirsi. Scusa per l'incomprensione. Naturalmente, entrambi i processi si avviano non appena appropriato 'start()' è ritornato. –

Problemi correlati