2013-08-11 26 views
8

Ich versuche, Python Multiprozessing zu lernen.Python Multiprocessing Documentation Beispiel

http://docs.python.org/2/library/multiprocessing.html aus dem Beispiel von „Um hier die einzelnen Prozess-IDs beteiligten zu zeigen, ist ein erweitertes Beispiel:“

from multiprocessing import Process 
import os 

def info(title): 
    print title 
    print 'module name:', __name__ 
    if hasattr(os, 'getppid'): # only available on Unix 
     print 'parent process:', os.getppid() 
    print 'process id:', os.getpid() 

def f(name): 
    info('function f') 
    print 'hello', name 

if __name__ == '__main__': 
    info('main line') 
    p = Process(target=f, args=('bob',)) 
    p.start() 
    p.join() 

Was genau an ich suche? Ich sehe, dass def f (name): wird nach der Info ('Hauptleitung') ist beendet, aber dieser synchrone Anruf wäre sowieso Standard. Ich sehe, dass die gleiche Prozessinformation ("Hauptlinie") die Eltern-PID von def f (Name) ist: aber nicht sicher, was "Multiprocessing" darüber ist.

Mit join() "Blockieren Sie den aufrufenden Thread, bis der Prozess, dessen Join() -Methode aufgerufen wird, endet". Ich weiß nicht, was der aufrufende Thread sein würde. In diesem Beispiel würde was beitreten() blockiert werden?

Antwort

25

Wie multiprocessing funktioniert, auf den Punkt gebracht:

  • Process() Spawns (fork oder ähnliches auf Unix-ähnlichen Systemen) eine Kopie des ursprünglichen Programms (unter Windows, die eine echte fork fehlt, das ist heikel und erfordert die besondere Sorgfalt, die die Moduldokumentation beachtet).
  • Die Kopie kommuniziert mit dem Original, um herauszufinden, dass (a) es eine Kopie ist und (b) es ausgehen und die target= Funktion aufrufen sollte (siehe unten).
  • An diesem Punkt sind das Original und die Kopie jetzt unterschiedlich und unabhängig und können gleichzeitig ausgeführt werden.

Da diese unabhängigen Prozesse sind, haben sie jetzt unabhängigen globalen Interpreter Locks (in CPython), so kann sowohl auf einer Multi-CPU-Box zu 100% eines CPU aufbrauchen, solange sie kämpfen nicht für andere untergeordnete (OS) Ressourcen. Das ist der "Multiprocessing" -Teil.

Natürlich müssen Sie irgendwann Daten zwischen diesen vermeintlich unabhängigen Prozessen hin und her senden, z. B. um Ergebnisse von einem (oder vielen) Arbeitsprozess (en) zurück zu einem "Haupt" -Prozess zu senden. (Es gibt eine gelegentliche Ausnahme, wo jeder völlig unabhängig ist, aber es ist selten ... plus gibt es die ganze Startsequenz selbst, die von gestartet wird.) So erzeugt jede Process Instanz - p, im obigen Beispiel - einen Kommunikationskanal zu seinem Eltern Schöpfer und umgekehrt (es ist eine symmetrische Verbindung). Das Modul multiprocessing verwendet das Modul pickle, um Daten in Strings umzuwandeln - die gleichen Strings, die Sie in Dateien mit pickle.dump speichern können - und sendet die Daten über den Kanal, "downwards" an Worker, um Argumente und solche, und "upwards" von Worker an zu senden Ergebnisse zurücksenden.

Schließlich, sobald Sie alle mit dem Abrufen der Ergebnisse fertig sind, beendet der Arbeiter (durch die Rückkehr von der target= Funktion) und sagt dem Elternteil, es ist fertig. Um sicherzustellen, dass alles geschlossen und aufgeräumt wird, sollte der Elternteil p.join() anrufen, um auf die "Ich bin fertig" -Nachricht des Arbeiters zu warten (eigentlich eine OS-Ebene auf Unix-ish-sysems).

Das Beispiel ist ein wenig albern, da die zwei gedruckten Nachrichten im Grunde genommen überhaupt keine Zeit benötigen, so dass sie "zur gleichen Zeit" laufen und keinen messbaren Gewinn haben. Aber angenommen, anstatt hello, f nur zu drucken, wurden die ersten 100.000 Stellen von π (3.14159 ...) berechnet. Sie könnten dann einen weiteren Process, p2 mit einem anderen Ziel g spawnen, das die ersten 100.000 Stellen von e (2.71828 ...) berechnet. Diese würden unabhängig voneinander laufen.Die Eltern könnten dann p.join() und p2.join() anrufen, um auf beide zu warten (oder noch mehr Arbeiter zu spawnen, um mehr Arbeit zu erledigen und mehr CPUs zu belegen, oder sogar erst einmal loslegen und eigene Arbeit machen).