我使用forkmanager同时运行任务而不是顺序运行任务。我已将实际代码转换为以下代表代码逻辑的示例代码。
#!/usr/bin/perl -w
use strict;
use Data::Dumper;
use Parallel::ForkManager;
my @array2d = () ;
my $dim1Items = 4;
my $dim2Items = 3;
my $dim1Manager = Parallel::ForkManager->new($dim1Items);
for (my $i = 0; $i <= $dim1Items ; $i++) {
$dim1Manager->start and next;
my $dim2Manager = Parallel::ForkManager->new($dim2Items);
for (my $j = 0; $j <= $dim2Items; $j++) {
$dim2Manager->start and next;
$array2d[$i][$j] = "$i\t$j" ;
$dim2Manager->finish;
}
$dim2Manager->wait_all_children;
$dim1Manager->finish;
}
$dim1Manager->wait_all_children;
print Dumper(@array2D) ;
然后我运行Dumper(@ 2dArray)来查看内容,但是我得到了空字符串,这意味着数组是空的。我尝试了我的值赋值语法而没有分叉,它起作用 - 所以我必须在分叉时做错事。
答案 0 :(得分:6)
分叉是创建一个新进程,它是当前进程的副本。在一个进程中更改变量不会在其他进程中更改类似命名的变量。
P :: FM确实提供了一种将数据传递回父进程的机制。它是documented标题下的“从子进程中检索DATASTRUCTURES”。
use Data::Dumper qw( Dumper );
use Parallel::ForkManager qw( );
use constant MAX_WORKERS => 10;
use constant { DIM1_ITEMS => 4, DIM2_ITEMS => 3 };
my @aoa;
my $pm = Parallel::ForkManager->new(MAX_WORKERS);
$pm->run_on_finish(sub {
my ($pid, $exit_code, $ident, $exit_signal, $core_dump, $result_ref) = @_;
my ($i, $j) = @$ident;
warn("Child $i,$j killed by signal $exit_signal"), return if $exit_signal;
warn("Child $i,$j exited with error $exit_code"), return if $exit_code;
warn("Child $i,$j encountered an unknown error"), return if !$result_ref;
$aoa[$i][$j] = $$result_ref;
});
for my $i (0..DIM1_ITEMS-1) {
for my $j (0..DIM2_ITEMS-1) {
$pm->start([ $i, $j ]) and next;
my $result = "$i\t$j";
$pm->finish(0, \$result);
}
}
$pm->wait_all_children();
print(Dumper(\@aoa));
(你有两个级别的P :: FM是没有意义的。你应该有一个F :: PM,其最大子女数量取决于你拥有的核心数量和一些实验。)
答案 1 :(得分:1)
正如ikegami所说,子进程在自己的内存空间中运行,并且它对变量的更改不会传播回父进程,除非您进行某种形式的进程间通信。 Forks::Super
模块使这种事情变得非常容易。
use Forks::Super;
my @array2d;
for my $i (0 .. 3) {
for my $j (0 .. 2) {
fork {
share => [ \$array2d[$i][$j] ],
sub => sub {
sleep 1 + rand 4;
$array2d[$i][$j] = "$i\t$j";
},
};
}
}
waitall;
print Dumper(\@array2d);