【问题标题】:Perl Parallel::ForkManager wait_all_children() takes excessively long timePerl Parallel::ForkManager wait_all_children() 耗时过长
【发布时间】:2011-01-26 14:05:27
【问题描述】:

我有一个使用Parallel::ForkManager 的脚本。然而,即使在所有子进程都完成之后,wait_all_children() 进程也需要非常长的时间。我知道的方法是打印出一些时间戳(见下文)。有谁知道是什么原因造成的(我的机器上有 16 个 CPU 内核)?

my $pm = Parallel::ForkManager->new(16);
for my $i (1..16) {
    $pm->start($i) and next;

    ... do something within the child-process ...

    print (scalar localtime), " Process $i completed.\n";
    $pm->finish();
}
print (scalar localtime), " Waiting for some child process to finish.\n"; 
$pm->wait_all_children();
print (scalar localtime), " All processes finished.\n"; 

显然,我将首先收到Waiting for some child process to finish 消息,其时间戳为7:08:35。然后我会得到Process i completed 消息的列表,最后一个在7:10:30。但是,直到7:16:33(!),我才收到消息All Processes finished。为什么在 7:10:30 和 7:16:33 之间会有 6 分钟的延迟?谢谢!

【问题讨论】:

  • 这是您正在运行的代码吗?有一个不那么微妙的语法错误。

标签: perl parallel-processing time-wait


【解决方案1】:

我试过了:

#!/opt/perl/bin/perl

use strict; use warnings;

use Parallel::ForkManager;

my $pm = Parallel::ForkManager->new(16);

for my $i (1..16) {
    $pm->start($i) and next;
    sleep rand 20;
    printf "%s : Process %d completed\n", scalar localtime, $i;
    $pm->finish;
}

printf "%s: Waiting for some child to finish\n", scalar localtime;
$pm->wait_all_children;

printf "%s: All processes finished.\n", scalar localtime; 

我明白了:

[sinan@archardy Src]$ ./y.pl
2010 年 3 月 11 日星期四 17:14:16:流程 3 完成
2010 年 3 月 11 日星期四 17:14:16:等待一些孩子完成
2010 年 3 月 11 日星期四 17:14:18:流程 8 完成
2010 年 3 月 11 日星期四 17:14:18:流程 14 完成
...
2010 年 3 月 11 日星期四 17:14:34:过程 12 完成
2010 年 3 月 11 日星期四 17:14:34:所有流程都已完成。

我在 Linux 上有 perl 5.10.1Parallel::ForkManager 版本 0.7.5

因此,我得出的结论是,无论您遇到什么问题,都是由于您发生的事情而发生的

# ... do something within the child-process ...

更新:问题是,您在finish 调用之前打印Process finished message。试试下面的版本:

#!/opt/perl/bin/perl

use strict; use warnings;

use Parallel::ForkManager;

my $pm = Parallel::ForkManager->new(16);
$pm->run_on_finish( sub {
    printf "%s : Process completed: @_\n", scalar localtime
});

for my $i (1..16) {
    $pm->start($i) and next;
    sleep rand 20;
    $pm->finish;
}

printf "%s: Waiting for some child to finish\n", scalar localtime;
$pm->wait_all_children;

printf "%s: All processes finished.\n", scalar localtime;

请参阅Callbacks in Parallel::ForkManager documentation 了解更多信息。如果延迟消失,那么您观察到的症状是由于您声称分叉进程在完成之前已经完成。

【讨论】:

  • 你说得对,思南。我忘了提到这种延迟不会每次都发生在我身上。只有当我的每个子进程都需要很长时间和许多系统资源才能完成时,才会发生这种情况。然而,困扰我的是,在打印最后一个“我完成的过程”之后,孩子们身上发生的任何事情都应该不再相关。但这是我得到的实际输出: 08:02:43 : Waiting for some children... 08:06:00 : group 1 完成。 ... 08:06:12:第 16 组完成。 08:07:03:全部完成。我想知道是否应该明确释放一些阻塞等待的内存/资源?
  • @Zhang18 使用run_on_finish 回调查看我的更新答案。
  • 我明白了。因此,如果我通过 run_on_finish() 打印时间戳,我会得到您所期望的(即,由于 wait_for_children 没有额外的等待时间)。但是,我的问题因此变成了为什么即使从字面上我已经在循环中到达了该打印语句,子进程也不被 fork 视为“完成”?可以肯定的是,我没有对循环内的任务做任何花哨的事情。它只是一堆算术计算加上一些数据库查询和文件 I/O。延迟似乎是由于 $pm->finish() 方法未能获取子进程的实际完成时间造成的。
  • @Zhang18 在$pm->finish 返回之前,孩子完成。请务必阅读perldoc.perl.org/functions/exit.html,尤其是最后一段。
猜你喜欢
  • 1970-01-01
  • 2018-12-09
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-17
  • 1970-01-01
相关资源
最近更新 更多