2010-02-19 13 views
8

Jestem bardzo nowy w tym module Parallel::ForkManager w Perlu i ma on wiele zalet, więc myślę, że obsługuje on to, czego potrzebuję i po prostu jeszcze się nie zorientowałem.Czy moduł Parallel :: ForkManager() obsługuje synchronizację zmiennych globalnych?

To, co muszę zrobić, to każdy proces potomny, zapisuje niektóre aktualizacje w globalnej mapie skrótu, zgodnie z kluczową wartością obliczoną w każdym procesie potomnym. Jednakże, kiedy przystąpię do żądania mapy skrótu poza pętlą for i oczekuję, że mapa skrótu zostanie zaktualizowana po pętli, okazuje się, że mapa skrótu pozostaje pusta. Oznacza to, że chociaż aktualizacja w pętli kończy się sukcesem (przez wydrukowanie wartości), poza pętlą nie jest.

Czy ktoś wie, jak napisać taki fragment kodu, który robi to, co chcę?

Odpowiedz

6

To nie jest problem specyficzny dla Perla, ale kwestia zrozumienia procesów w stylu Unix. W przypadku nowego procesu żadna z pamięci nie jest domyślnie współużytkowana między procesami. Istnieje kilka sposobów na osiągnięcie tego, czego chcesz, w zależności od potrzeb.

Jedną z prostych metod jest użycie czegoś takiego, jak BerkeleyDB do powiązania skrótu z plikiem na dysku. Związany hasz można zainicjować przed rozwidleniem, a następnie każdy proces potomny będzie miał do niego dostęp. Pliki BerkeleyDB zostały zaprojektowane tak, aby zapewnić bezpieczny dostęp z wielu procesów jednocześnie.

Bardziej zaangażowaną metodą byłoby użycie jakiejś formy komunikacji między procesami. Szczegółowe informacje na temat uzyskiwania takich można znaleźć na stronie podręcznika: perlipc, która zawiera szczegółowe informacje na temat kilku metod IPC obsługiwanych przez Perl.

Ostatnim podejściem, jeśli twój Perl je obsługuje, jest używanie wątków i dzielenie między nimi zmiennych.

4

Każde wywołanie fork generuje zupełnie nowy proces, więc aktualizacje zmiennej mieszającej w procesie potomnym nie są widoczne w obiekcie nadrzędnym (a zmiany w obiekcie nadrzędnym po wywołaniu fork nie są widoczne w elemencie potomnym).

Można użyć threads (i zobacz także threads::shared), aby zmiana zapisana w jednym wątku mogła być zapisana w innym wątku.

Inną opcją jest wykorzystanie komunikacji międzyprocesowej do przekazywania wiadomości między procesami nadrzędnymi i podrzędnymi. Moduł Forks::Super (którego jestem autorem) może sprawić, że nie będzie to bolało.

Lub twoje procesy podrzędne mogą zapisywać niektóre dane wyjściowe do plików. Gdy proces nadrzędny je zapisuje, może załadować dane z tych plików i odpowiednio zaktualizować swoją globalną mapę skrótu.

+0

Dziękuję wszystkim, teraz rozumiem! Spodziewałem się, że ForkManager() zajmie się tym problemem. :-) W moim przypadku IPC może być przesadą. Podoba mi się zwięzły sposób korzystania z ForkManager(), więc czy istnieje prosty sposób na udostępnienie globalnej tablicy skrótów między procesami za pomocą ForkManager()? – galactica

+3

@Jin: Pobieranie danych z jednego procesu do drugiego * to * IPC. To właśnie oznacza. Nie musi to być jednak trudne. – hobbs

+0

@Jin: tak, użyj powiązanego skrótu; zobacz http://search.cpan.org/perldoc/BerkeleyDB na jeden. – ysth

2

Przeczytaj sekcję "ODZYSKIWANIE DANYSTRUKTUR z procesu potomnego" z man Parallel :: ForkManager. Istnieją wywołania zwrotne, dane dziecka mogą być wysyłane, a rodzic może je odzyskać i zapełnić struktury danych.