Как я могу разделить простой скаляр (переменная счетчика) между вилками в Perl? - PullRequest
1 голос
/ 14 апреля 2011

Я писал программу, которая много раз разветвляется, и каждая из разветвлений может также разбиваться на более мелкие части.

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

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

В качестве примера, который поможет сделать это более конкретным, каждый из дочерних элементов создаст файл $unique_id.storable, содержащий данные, обработанные соответствующим дочерним элементом.

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

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

Как я могу разделить переменную счетчика, простой скаляр, между вилками?

Я понимаю, что вопросы межпроцессного взаимодействия довольно часто встречаются в сетях, но я замечаю, что многие решения касаются общей проблемы распределения произвольных объемов данных между процессами. Мне просто нужно поделиться одним скаляром, поэтому я задаюсь вопросом, можно ли решить мою проблему более простым способом. В идеале, в идеале, на самом деле, я бы предпочел решение, не включающее «нестандартный» модуль. Я вижу, что IPC::Shareable иногда рекомендуется, но мне интересно, может ли это быть излишним для моей проблемы, и в любом случае это один из тех "нестандартных" модулей.

Будет ли разумно, если я сделаю свой $unique_id PID? Возможно ли, что родительская программа, работающая в течение, скажем, одной недели на интенсивно используемой машине, могла бы повторно использовать PID и не гарантировать уникальность?

Буду признателен за любые советы, которые люди могут дать.

Ответы [ 3 ]

4 голосов
/ 14 апреля 2011

Почему бы вам не передать идентификатор? Корневой процесс порождает

1
2
...

Эти, в свою очередь, порождают

1.1
1.2
...

2.1
2.2
...

...

и т. Д.

2 голосов
/ 14 апреля 2011

Вы можете использовать pid и быть уверенным, что он уникален, если родитель будет пожинать потомка только после того, как родитель обработает вывод дочернего элемента.

# Wait for a child to terminate, but don't reap it yet.
my $pid = waitpid(-1, WNOWAIT);

# Collect data from the file for child $pid
...

# Reap the child.
waitpid($pid, 0);  

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

2 голосов
/ 14 апреля 2011

Я бы, вероятно, использовал немного другой подход: вы могли бы обрабатывать все через имя файла ...

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

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

Имена файлов в конечном итоге выглядят немного громоздкими, но онипросто временные файлы, верно?

Полученные имена файлов будут выглядеть примерно так:

<job_id>_<pid>_<created_time>.storable

Тогда родитель просто ищет все файлы <job_id>_*.storable

...