1

I am using forkmanager to run tasks at the same time instead of sequentially. I have turned my actual code into the following example code that represents my code's logic.

#!/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) ; 

Then I run Dumper(@2dArray) to see the contents, but I get the null string, meaning the array is empty. I tried my value assignment syntax without forking and it works - so I must be doing something wrong in forking.

4

2 回答 2

6

分叉是创建一个新进程,它是当前进程的副本。在一个进程中更改变量不会更改其他进程中类似命名的变量。

P::FM 确实提供了一种将数据传递回父进程的机制。它记录在“从子进程中检索数据结构”标题下。

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,其最大子节点数取决于你拥有的核心数量和一些实验。)

于 2013-06-06T22:39:46.753 回答
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);
于 2013-06-07T00:23:42.183 回答