2010-02-19 7 views
8

Ich bin sehr neu zu diesem Parallel::ForkManager Modul in Perl und es hat eine Menge Credits, so denke ich, dass es unterstützt, was ich brauche, und ich habe gerade noch nicht herausgefunden.Unterstützt das Modul Parallel :: ForkManager() die Synchronisation auf globalen Variablen?

Was ich tun muss, ist in jedem Kindprozess, es schreibt einige Updates in eine globale Hash-Map, entsprechend dem Schlüsselwert, der in jedem Kindprozess berechnet wird. Wenn ich jedoch eine Hash-Map außerhalb der for-Schleife beanspruche und erwarte, dass die Hash-Map nach der Schleife aktualisiert wird, stellt sich heraus, dass die Hash-Map leer bleibt. Dies bedeutet, obwohl das Update innerhalb der Schleife erfolgreich ist (durch Ausdrucken des Wertes), ist dies außerhalb der Schleife nicht der Fall.

Weiß jemand, wie man ein solches Stück Code schreibt, der tut, was ich will?

Antwort

6

Dies ist nicht wirklich ein Perl-spezifisches Problem, sondern eine Frage des Verständnisses von Unix-ähnlichen Prozessen. Wenn Sie einen neuen Prozess fork haben, wird keiner der Speicher standardmäßig zwischen Prozessen freigegeben. Es gibt ein paar Möglichkeiten, wie Sie erreichen können, was Sie wollen, je nachdem, was Sie brauchen.

Ein einfacher Weg wäre, etwas wie BerkeleyDB zu verwenden, um einen Hash mit einer Datei auf der Festplatte zu verknüpfen. Der gebundene Hash kann vor der Verzweigung initialisiert werden, und dann hat jeder untergeordnete Prozess Zugriff darauf. BerkeleyDB-Dateien sind für den sicheren Zugriff aus mehreren Prozessen gleichzeitig konzipiert.

Eine kompliziertere Methode wäre die Verwendung einer Form der Kommunikation zwischen Prozessen. Für alle wichtigen Details zum Erreichen eines solchen Ziels, siehe die Manpage perlipc, die Details zu verschiedenen IPC-Methoden enthält, die von Perl unterstützt werden.

Ein letzter Ansatz, wenn Ihr Perl es unterstützt, besteht darin, Threads zu verwenden und Variablen zwischen ihnen zu teilen.

4

Jeder fork Aufruf erzeugt ein völlig neues Verfahren, so dass Updates auf ein Hash-Variable in einem untergeordneten Prozess in den Eltern nicht sichtbar ist (und Änderungen an den Eltern nach dem fork Aufruf sind in dem Kind nicht sichtbar).

Sie könnten threads (und siehe auch threads::shared) verwenden, um eine in einem Thread geschriebene Änderung in einen anderen Thread schreiben zu lassen.

Eine andere Option besteht darin, die Interprozesskommunikation zu verwenden, um Nachrichten zwischen übergeordneten und untergeordneten Prozessen zu übergeben. Das Forks::Super Modul (von dem ich der Autor bin) kann dies weniger Kopfschmerzen machen.

Oder Ihre untergeordneten Prozesse könnten einige Ausgaben in Dateien schreiben. Wenn der Parent-Prozess sie abholt, kann er die Daten aus diesen Dateien laden und seine globale Hash-Map entsprechend aktualisieren.

+0

Danke an alle, jetzt verstehe ich! Ich habe erwartet, dass der ForkManager() sich um dieses Problem kümmert. :-) In meinem Fall könnte IPC übertrieben sein. Ich mag die prägnante Art der Verwendung von ForkManager(), gibt es also eine einfache Möglichkeit, eine globale Hash-Map zwischen Prozessen mit ForkManager() zu teilen? – galactica

+3

@Jin: Daten von einem Prozess zu einem anderen erhalten * ist * IPC. Das ist was es bedeutet. Es muss jedoch nicht schwer sein. – hobbs

+0

@Jin: Ja, verwende einen gebundenen Hash; siehe http://search.cpan.org/perldoc/BerkeleyDB für einen. – ysth

2

Lesen Sie den Abschnitt "ABRUFEN VON DATASTRUCTURES aus untergeordneten Prozessen" von man Parallel :: ForkManager. Es gibt Callbacks, Kinddaten können gesendet werden und Eltern können sie abrufen und Datenstrukturen auffüllen.