multiprocessing.Poolha 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.Queuenon è 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.workersotto il cofano. Questa funzione si occupa di elaborare nuove "attività" trasferite all'interno del Pool Pool._inqueuee di rinviare i risultati al genitore tramite Pool._outqueue. Il tuo specificato funcverrà eseguito entro multiprocessing.pool.worker. funcha solo returnqualcosa e il risultato verrà automaticamente rimandato al genitore.
.apply_async() immediatamente (in modo asincrono) restituisce un AsyncResultoggetto (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 timeoutparametro -per .get()non interromperà l'effettiva elaborazione dell'attività all'interno del lavoratore, ma sblocca solo il genitore in attesa sollevando un multiprocessing.TimeoutError.