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

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

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

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

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

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

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

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

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

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

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


person EMiller    schedule 14.04.2011    source источник
comment
Да, так что опубликованные решения не касаются напрямую моего желания использовать какую-либо форму IPC, но они решают мою проблему, заключающуюся в наличии уникальной переменной-счетчика между ответвлениями моей программы на Perl.   -  person EMiller    schedule 20.04.2011


Ответы (3)


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

1
2
...

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

1.1
1.2
...

2.1
2.2
...

...

и так далее.

person ikegami    schedule 14.04.2011
comment
Идентификатор? Вы имеете в виду ПИД? - person EMiller; 14.04.2011

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

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

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

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

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

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

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

person kshep    schedule 14.04.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);  

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

person ikegami    schedule 14.04.2011