Sto cercando di capire un po 'cosa sta succedendo dietro le quinte quando si utilizza il metodo apply_sync di un pool di multiprocessing.Chi esegue la richiamata quando si utilizza il metodo apply_async di un lotto di multiprocessing?
Chi esegue il metodo di richiamata? È il processo principale che ha chiamato apply_async?
Diciamo che invio un intero gruppo di comandi apply_async con i callback e quindi proseguo con il mio programma. Il mio programma sta ancora facendo le cose quando termina l'inizio di apply_async. Come viene eseguito il callback come "processo principale" mentre il processo principale è ancora occupato con lo script?
Ecco un esempio.
import multiprocessing
import time
def callback(x):
print '{} running callback with arg {}'.format(multiprocessing.current_process().name, x)
def func(x):
print '{} running func with arg {}'.format(multiprocessing.current_process().name, x)
return x
pool = multiprocessing.Pool()
args = range(20)
for a in args:
pool.apply_async(func, (a,), callback=callback)
print '{} going to sleep for a minute'.format(multiprocessing.current_process().name)
t0 = time.time()
while time.time() - t0 < 60:
pass
print 'Finished with the script'
L'output è simile
PoolWorker-1 esegue func con arg 0
PoolWorker-2 esegue func con arg 1
PoolWorker-3 esecuzione func con arg 2
MainProcess andare a dormire per un minuto < - processo principale è occupato
PoolWorker-4 func esecuzione con arg 3
PoolWorker-1 esegue func con arg 4
PoolWorker-2 esegue func con arg 5
PoolWorker-3 esecuzione func con arg 6
PoolWorker-4 esecuzione func con arg 7
MainProcess esecuzione callback w con arg 0 < - processo principale che esegue la richiamata mentre è ancora nel ciclo while !!
MainProcess callback esecuzione con arg 1
MainProcess esecuzione richiamata con arg 2
MainProcess callback esecuzione con arg 3
MainProcess callback esecuzione con arg 4
PoolWorker-1 func esecuzione con arg 8
...
finito con lo script
Come viene MainProcess in esecuzione la richiamata mentre è nel bel mezzo di quel ciclo while ??
Esiste questa dichiarazione sul callback nella documentazione per multiprocessing.Pool che sembra un suggerimento ma non lo capisco.
apply_async (func [, args [, kwds [, callback]]])
Una variante del metodo apply() che restituisce un oggetto risultato.
Se la callback è specificata, dovrebbe essere un callable che accetta un singolo argomento. Quando il risultato diventa pronto, viene applicato il callback (a meno che la chiamata non abbia avuto esito positivo). la callback dovrebbe essere completata immediatamente poiché altrimenti il thread che gestisce i risultati verrà bloccato.
Grazie Dano per aver trovato il tempo di scrivere una risposta così dettagliata! Se ho capito bene, il pool crea un * singolo * nuovo thread (il result_handler) il cui compito è quello di attendere che apply_async sia completato e quindi chiama il callback nel thread del result_handler (che fa parte del MainProcess). I callback (per un oggetto pool singolo) verranno chiamati in sequenza? Cioè Un gruppo di apply_async può finire insieme ma i callbacks verranno eseguiti uno ad uno in serie dal result_handler? – Alex
Un'altra domanda. Cosa succede se la funzione di callback e lo script principale funzionano entrambi con gli stessi oggetti (nel MainProcess)? Potrebbe esserci un comportamento imprevedibile? Cioè se il callback e qualcosa più avanti nello script principale tentano entrambi di scrivere sullo stesso file o modificare lo stesso array. Quando viene effettivamente eseguito il callback, chissà cosa farà lo script principale in quel momento. – Alex
@Alex Sì, i callback saranno eseguiti in modo squenziale.Il thread '_result_handler' estrae una task completata dalla coda, chiama' _set' (che esegue la callback), quindi passa a quella successiva. Questo è il motivo per cui la documentazione dice di assicurarsi che il callback sia completato immediatamente; l'esecuzione della richiamata blocca altri risultati dall'elaborazione. – dano