Parallel :: ForkManager слишком много времени, чтобы запустить функцию финиша - PullRequest
0 голосов
/ 29 октября 2018

Я использую обычный модуль Parallel :: ForkManager в Perl. Я выполняю около 10 дочерних процессов. Функция pass_thresholds занимает несколько миллисекунд или наносекунд (проверено). В случае, если я запускаю все процессы один за другим (без Parallel :: ForkManager), весь процесс занимает 80-250 миллисекунд. Если я запускаю их параллельно, весь процесс занимает не менее 1 секунды. Я обнаружил, что вилка тратит 1 секунду, чтобы запустить функцию финиша. Я поставил таймер, когда дочерний процесс закончил свою работу и должен перейти к функции «Finish». Одна секунда - это слишком много для моего развития.

sub parallel_execute {
    my $this = shift;
    foreach my $a (@a_array) {
        my $pid = $this->{fork_manager}->start and next;
        my $res = $a->passes_thresholds();
        $a->{timer} = Benchmark::Timer->new();
        $svc->{timer}->start;
        $this->{fork_manager}->finish(0,{a => $a, plugin_result => $res});
    }
}

$this->{fork_manager}->run_on_finish( sub {
    my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $data_structure_reference) = @_;
    my $a = $data_structure_reference->{a};
    if (exists $a->{timer}) {
        $a->{timer}->stop;
        debug "took: " . $a->{timer}->report;
    }
});

У вас есть идея, почему для запуска команды финиша потребовалась не менее 1 секунды?

(я использую сервер Unix и Perl 5.10)

Ответы [ 2 ]

0 голосов
/ 31 октября 2018

Спасибо вам всем, я нашел проблему. Модуль ForManager имеет параметр waitpid_blocking_sleep, который по умолчанию определен как 1 секунда. Есть функция set_waitpid_blocking_sleep, с помощью которой мы можем определить этот параметр (время ожидания). Мы можем установить ноль или доли секунды. Я установил этот параметр на ноль, и это исправило мою проблему.

0 голосов
/ 30 октября 2018

Обратный вызов on_finish вызывается только тогда, когда P :: FM пожинает ребенка, а P :: FM только пожинает ребенка при трех условиях:

  • Когда вызывается $pm->start и количество детей, которые были запущены, но не собраны, равно максимальному.
  • Когда вызывается $pm->reap_finished_children.
  • Когда вызывается $pm->wait_all_children.

Может быть произвольно большая задержка между выходом ребенка и одним из вышеуказанных событий. Добавление следующего к вашей программе должно устранить эту задержку:

$SIG{CHLD} = sub { $pm->reap_finished_children };

Кстати, если работа, выполняемая вашим ребенком, занимает «несколько миллисекунд или наносекунд», вы фактически замедляете работу с помощью P :: FM. Данные, передаваемые на finish, сериализуются и записываются на диск, затем считываются с диска и десериализуются для обратного вызова on_finish!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...