Parallel :: ForkManager需要太多时间才能启动“完成”功能

时间:2018-10-29 13:21:11

标签: perl parallel-processing

我在Perl中使用常规的Parallel :: ForkManager模块。我执行大约10个子进程。 “ passes_thresholds”功能需要几毫秒或十亿分之一秒(选中)。如果我一个接一个地运行所有进程(没有Parallel :: ForkManager),整个过程将花费80-250毫秒。如果我将它们并行运行,则整个过程至少需要1秒钟。我发现前叉花了1秒钟来启动“完成”功能。当子进程完成工作时,我放置了一个计时器,应该进入“完成”功能。一秒钟对于我的发展来说太过分了。

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 :(得分:2)

谢谢大家,我发现了问题。 ForManager模块具有“ waitpid_blocking_sleep”参数,默认情况下定义为1秒。有一个名为“ set_waitpid_blocking_sleep”的函数,我们可以定义此参数(睡眠时间)。我们可以设置零或秒的分数。我将此参数设置为零,并解决了我的问题。

答案 1 :(得分:1)

仅当P :: FM收割孩子时调用on_finish回调,而P :: FM仅在以下三种情况下收割孩子:

  • 调用$pm->start时,已开始但未收获的子代数量等于最大值。
  • 调用$pm->reap_finished_children时。
  • 调用$pm->wait_all_children时。

孩子离开与上述事件之一之间可能会有任意漫长的延迟。在您的程序中添加以下内容可以消除这种延迟:

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

顺便说一句,如果您的孩子完成的工作仅花费“几毫秒或十亿分之一秒”,实际上您正在通过使用P :: FM放慢速度。传递给finish的数据被序列化并写入磁盘,然后从磁盘读取并反序列化以进行on_finish回调!