2015-04-09 18 views
11

La documentazione joblib contengono il seguente avviso:Perché è importante proteggere il loop principale quando si usa joblib.Parallel?

In Windows, è importante per proteggere il ciclo principale di codice per evitare la deposizione delle uova ricorsiva di sottoprocessi quando si utilizza joblib.Parallel. In altre parole, si dovrebbe scrivere il codice come questo:

import .... 

def function1(...): 
    ... 

def function2(...): 
    ... 

... if __name__ == '__main__': 
    # do stuff with imports and functions defined about 
    ... 

Nessun codice dovrebbe funzionare al di fuori dei “if __name__ ==‘__main__’” blocchi, solo le importazioni e le definizioni.

Inizialmente, ho pensato che questo era solo per evitare contro il caso strano occasionale in cui una funzione passata al joblib.Parallel chiamato il modulo in modo ricorsivo, il che significa che è stata generalmente buona pratica, ma spesso inutili. Tuttavia, non ha senso per me perché questo sarebbe solo un rischio su Windows. Inoltre, this answer sembra indicare che la mancata protezione del ciclo principale ha comportato il codice in esecuzione più volte più lentamente di quanto avrebbe altrimenti per un semplice problema non ricorsivo.

Per curiosità, ho eseguito l'esempio super-semplice di un ciclo parallelo imbarazzante dai documenti di joblib senza proteggere il ciclo principale su una finestra di Windows. Il terminale si trasmette con il seguente errore fino a quando ho chiuso:

ImportError: [joblib] Attempting to do parallel computing without protecting your import on a system that does not suppo 
rt forking. To use parallel-computing in a script, you must protect you main loop using "if __name__ == '__main__'". Ple 
ase see the joblib documentation on Parallel for more information 

La mia domanda è, per quanto riguarda l'implementazione di Windows del joblib richiede il ciclo principale da proteggere in ogni caso?

Ci scusiamo se questa è una domanda di base. Sono nuovo nel mondo della parallelizzazione, quindi potrei semplicemente mancare alcuni concetti di base, ma non ho potuto trovare questo problema discusso esplicitamente da nessuna parte.

Infine, voglio sottolineare che questo è puramente accademico; Capisco perché sia ​​generally good practice a scrivere il proprio codice in questo modo, e continuerà a farlo indipendentemente da joblib.

risposta

16

Ciò è necessario perché Windows non dispone di fork(). A causa di questa limitazione, Windows deve reimportare il modulo __main__ in tutti i processi figli che genera, al fine di ricreare lo stato del genitore nel figlio. Ciò significa che se si dispone del codice che genera il nuovo processo a livello di modulo, verrà eseguito in modo ricorsivo in tutti i processi figli. La protezione if __name__ == "__main__" viene utilizzata per impedire che il codice nell'ambito del modulo venga rieseguito nei processi figli.

questo non è necessario in Linux, perché fa avere fork(), che gli permette di fork di un processo figlio che mantiene lo stesso stato del genitore, senza re-importare il modulo __main__.

+0

Interessante, grazie! Devo dire, se stavo progettando un sistema operativo, penserei che la possibilità di eseguire il fork dei processi sarebbe piuttosto semplice e desiderabile ... ma immagino che questa sia solo un'altra strana limitazione di Windows. – Joe