Поддерживает ли модуль Parallel :: ForkManager () синхронизацию с глобальными переменными? - PullRequest
8 голосов
/ 19 февраля 2010

Я очень новичок в этом Parallel :: ForkManager модуле в Perl, и у него много кредитов, поэтому я думаю, что он поддерживает то, что мне нужно, и я просто еще не понял.

В каждом дочернем процессе мне нужно записать некоторые обновления в глобальную хэш-карту в соответствии со значением ключа, вычисленным в каждом дочернем процессе. Однако, когда я продолжаю запрашивать хеш-карту вне цикла for и ожидаю, что хеш-карта обновляется после цикла, оказывается, что хеш-карта остается пустой. Это означает, что, хотя обновление внутри цикла выполняется успешно (путем распечатывания значения), вне цикла это не так.

Кто-нибудь знает, как написать такой кусок кода, который делает то, что я хочу?

Ответы [ 3 ]

6 голосов
/ 19 февраля 2010

Это на самом деле не специфическая для Perl проблема, а вопрос понимания процессов в стиле Unix. Когда вы fork новый процесс, по умолчанию ни одна из памяти не распределяется между процессами. Есть несколько способов добиться того, чего вы хотите, в зависимости от того, что вам нужно.

Одним простым способом было бы использовать что-то вроде BerkeleyDB , чтобы связать хеш с файлом на диске. Связанный хэш может быть инициализирован до того, как вы разветвитесь, и тогда каждый дочерний процесс получит к нему доступ. Файлы BerkeleyDB предназначены для безопасного доступа к нескольким процессам одновременно.

Более сложным методом было бы использование некоторой формы межпроцессного взаимодействия. Все подробности о том, как этого добиться, см. На справочной странице perlipc , в которой подробно рассказывается о нескольких методах IPC, поддерживаемых Perl.

Последний подход, если ваш Perl поддерживает это, - это использовать потоки и делить переменные между ними.

4 голосов
/ 19 февраля 2010

Каждый вызов fork генерирует новый процесс, поэтому обновления хеш-переменной в дочернем процессе не видны в родительском (и изменения в родительском после вызова fork не видны в дочернем).

Вы можете использовать threads (и см. Также threads::shared), чтобы изменение, записанное в одном потоке, было доступно для записи в другом потоке.

Другой вариант - использовать межпроцессное взаимодействие для передачи сообщений между родительскими и дочерними процессами. Модуль Forks::Super (автором которого я являюсь) может уменьшить эту головную боль.

Или ваши дочерние процессы могут записывать некоторые выходные данные в файлы. Когда родительский процесс получает их, он может загрузить данные из этих файлов и соответствующим образом обновить свою глобальную хэш-карту.

2 голосов
/ 18 июня 2012

Прочтите раздел «ПОЛУЧЕНИЕ ДАННЫХ СТРУКТУР от дочерних процессов» из man Parallel :: ForkManager Существуют обратные вызовы, дочерние данные могут быть отправлены, а родительский объект может их извлечь и заполнить структуры данных.

...