multiprocessing.Pool
ha già una coda dei risultati condivisa, non è necessario coinvolgere ulteriormente un file Manager.Queue
. Manager.Queue
è una queue.Queue
(coda multithreading) nascosta, situata su un processo server separato ed esposta tramite proxy. Ciò aggiunge un sovraccarico aggiuntivo rispetto alla coda interna del pool. Contrariamente a quanto ci si affida alla gestione dei risultati nativa di Pool, Manager.Queue
non è garantito che i risultati vengano ordinati anche in.
I processi di lavoro non vengono avviati .apply_async()
, questo accade già quando si crea un'istanza Pool
. Ciò che è iniziato quando si chiama pool.apply_async()
è un nuovo "lavoro". I processi di lavoro di Pool eseguono la funzione multiprocessing.pool.worker
sotto il cofano. Questa funzione si occupa di elaborare nuove "attività" trasferite all'interno del Pool Pool._inqueue
e di rinviare i risultati al genitore tramite Pool._outqueue
. Il tuo specificato func
verrà eseguito entro multiprocessing.pool.worker
. func
ha solo return
qualcosa e il risultato verrà automaticamente rimandato al genitore.
.apply_async()
immediatamente (in modo asincrono) restituisce un AsyncResult
oggetto (alias per ApplyResult
). Devi chiamare .get()
(sta bloccando) su quell'oggetto per ricevere il risultato effettivo. Un'altra opzione sarebbe registrare una funzione di callback , che viene attivata non appena il risultato è pronto.
from multiprocessing import Pool
def busy_foo(i):
"""Dummy function simulating cpu-bound work."""
for _ in range(int(10e6)): # do stuff
pass
return i
if __name__ == '__main__':
with Pool(4) as pool:
print(pool._outqueue) # DEMO
results = [pool.apply_async(busy_foo, (i,)) for i in range(10)]
# `.apply_async()` immediately returns AsyncResult (ApplyResult) object
print(results[0]) # DEMO
results = [res.get() for res in results]
print(f'result: {results}')
Output di esempio:
<multiprocessing.queues.SimpleQueue object at 0x7fa124fd67f0>
<multiprocessing.pool.ApplyResult object at 0x7fa12586da20>
result: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Nota: la specifica del timeout
parametro -per .get()
non interromperà l'effettiva elaborazione dell'attività all'interno del lavoratore, ma sblocca solo il genitore in attesa sollevando un multiprocessing.TimeoutError
.