在修改pid条件时,我有两个问题:Parallel :: ForkManager。
问题1:举一个简单的例子,
use strict;
use warnings;
use Parallel::ForkManager;
use IO::Socket ;
my $np = 32 ;
my $pm = Parallel::ForkManager->new($np);
$| = 1 ;
sub do_something{ #an example for 3 second delay
my $port = shift @_ ;
my $tgt = 192.168.0.1 ;
my $sock = IO::Socket::INET->new(PeerAddr=>"$tgt:$port",Proto='tcp',Timeout=>3) ;
$sock ? return $sock : return 0 ;
}
foreach (1..64) {
$pm->start and next ;
do_something($_) ;
$pm->finish ;
}
$pm->wait_all_children ;
以上脚本可以使用
time perl simple_script.pl
real 0m7.109s
user 0m0.237s
sys 0m0.080s
修改
$pm->start and next ;
do_something($_) ;
到
$pm->start and next or do_something($_) ;
或
!($pm->start) or do_something($_) ;
似乎也有效,但不是预期的。
time perl modified_script.pl
real 3m12.307s
user 0m0.237s
sys 0m0.080s
似乎另外两个修改版本一次运行一个进程。
问题2:
有没有其他方法可以在不使用foreach循环中的下一个内容的情况下执行相同的操作?这样,脚本可以适用于map而不是foreach循环。
P.S:分叉和对象创建不是我的优点。
编辑:删除&根据建议。
答案 0 :(得分:0)
如果你改变这个循环
foreach (1..64) {
$pm->start and next;
do_something($_);
$pm->finish;
}
到这个
foreach (1..64) {
!($pm->start) or do_something($_);
}
然后你删除了终止每个孩子的$pm->finish
电话。这意味着子进程将继续执行for
循环,尝试启动自己的子进程,这将失败(因为子进程需要自己的Parallel::ForkManager
对象 - 他们不能使用父进程)等等他们每次都会do_something
循环。此外,由于孩子们在多次执行子程序时会被延迟,因此在所有64个孩子都开始运动需要更长的时间,因为你在任何时候都有32个孩子的限制。
你可以写
for ( 1 .. 64 ) {
my $pid = $pm->start;
if ( $pid == 0 ) {
do_something($_);
$pm->finish;
}
}
$pm->wait_all_children;
但正如我在评论中所说的那样,如果这只是为了让您滥用map
而不是使用for
那么请不要这样做
答案 1 :(得分:0)
您声明的更改不会导致此过程花费更长时间。因此,我将专注于您的问题:如何将foreach循环转换为map
循环。
for (LIST) BLOCK
可以写为map BLOCK LIST
。问题是你不能使用next
因为循环的每次传递都会返回一些东西(如果只是空列表)。
my $pm = ...;
map {
if (!$pm->start) {
do_something($_);
$pm->finish;
}
()
} 1..64;
$pm->wait_all_children();
或
sub child {
my ($job) = @_;
...
exit();
}
{
my $pm = ...;
map { $pm->start or child($_) } 1..64;
$pm->wait_all_children();
}
我不知道你为什么要那样做。它只会让代码更难阅读。