2010-02-19 2 views
8

Я очень новичок в этом модуле Parallel::ForkManager в Perl, и у него много кредитов, поэтому я думаю, что он поддерживает то, что мне нужно, и я еще не понял.Поддерживает ли Parallel :: ForkManager() синхронизацию глобальных переменных?

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

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

ответ

6

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

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

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

Последний подход, если ваш Perl поддерживает его, заключается в использовании потоков и обмена между ними переменными.

4

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

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

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

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

+0

Спасибо всем, теперь я понимаю! Я ожидал, что ForkManager() позаботится об этой проблеме. :-) В моем случае IPC может быть излишним. Мне нравится сжатый способ использования ForkManager(), так есть ли простой способ совместного использования глобальной хэш-карты между процессами с помощью ForkManager()? – galactica

+3

@Jin: Получение данных из одного процесса в другой * является * IPC. Вот что это значит. Однако это не должно быть сложно. – hobbs

+0

@Jin: да, используйте привязанный хеш; см. http://search.cpan.org/perldoc/BerkeleyDB для одного. – ysth

2

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

 Смежные вопросы

  • Нет связанных вопросов^_^