Warum sterben Python Multiprocessing Workers nicht?

9

Ich verwende die Python-Multiprocessing-Funktionalität, um einige Funktionen über einige Elemente abzubilden. Etwas nach dem Motto:

%Vor%

Im Allgemeinen verwende ich Tests in ipython mit cPython und Pypy. Ich habe bemerkt, dass die erzeugten Prozesse oft nicht getötet werden, also beginnen sie sich zu akkumulieren, wobei jeder einen Gig von Ram benutzt. Dies passiert, wenn während einer Berechnung ctrl-k gedrückt wird, was Multiprozessing in eine große Verwirrung versetzt. Aber selbst wenn die Berechnung beendet wird, werden diese Prozesse in Pypy nicht absterben.

Laut der Dokumentation sollte der Pool, wenn der Müll gesammelt wird, terminate() aufrufen und alle Prozesse beenden. Was passiert hier? Muss ich explizit close() aufrufen? Wenn ja, gibt es eine Art Kontextmanager, der die Ressourcen (d. H. Die Prozesse) ordnungsgemäß verwaltet?

Dies ist unter Mac OS X Yosemite.

    
Ant6n 27.07.2015, 19:00
quelle

1 Antwort

2

Die Müllsammlung von PyPy ist faul. Wenn Sie also close nicht aufrufen, bedeutet das, dass Pool "irgendwann" gesäubert wird, aber das bedeutet möglicherweise nicht "in absehbarer Zeit".

Sobald die Pool richtig close d ist, werden die Worker beendet, wenn sie keine Aufgaben mehr haben. Ein einfacher Weg, um sicherzustellen, dass Pool in Python vor 3.3 geschlossen ist, ist:

%Vor%

Hinweis: Ich habe auch die explizite Konvertierung in list entfernt (sinnlos, da map den enumerate Iterator für Sie iteriert) und die Ergebnisse direkt zurückgegeben (es ist nicht nötig, einen Namen zu vergeben, nur um zurückzukehren die nächste Zeile).

Wenn Sie im Ausnahmefall (bei Python vor Version 3.3) eine sofortige Beendigung sicherstellen möchten, verwenden Sie einen try / finally-Block oder schreiben Sie einen einfachen Kontextmanager (der für andere Orte wiederverwendet werden kann, an denen Sie a Pool ):

%Vor%

Der Ansatz von terminating ist insofern überlegen, als er garantiert, dass die Prozesse sofort beendet werden; Wenn Sie Threads anderswo in Ihrem Hauptprogramm verwenden, werden die Pool Worker theoretisch mit Nicht-Daemon-Threads gegabelt, wodurch die Prozesse am Leben bleiben, selbst wenn der Worker-Task-Thread beendet wird. terminating verbirgt dies, indem die Prozesse zwangsweise beendet werden.

Wenn Ihr Interpreter Python 3.3 oder höher ist, ist der terminating -Ansatz in Pool integriert, so dass kein spezieller Wrapper für die with -Anweisung benötigt wird, with multiprocessing.Pool(initializer=initWorker, initargs=(globalData,)) as pool: funktioniert direkt.

    
ShadowRanger 30.07.2015, 14:53
quelle