当子进程必须写入公共变量时,在perl中进行分叉

时间:2014-07-29 23:07:39

标签: linux perl parallel-processing fork

我正在处理大型文本文件,并希望从并行处理中受益。我打算将文件分解为与系统上的核心一样多的子文件,并在单独的分叉过程中读取每个子文件。

然而,这种方法的一个问题是需要将输入数据写入公共阵列。我对分支的基本理解是这样的操作是不可行的,并且必须将数据写入单独的数组。这是真的吗?

如果是这样,最好的方法是简单地等待所有子进程完成,然后将数组连接成单个结构以便后续处理?我编写了一个最小的例子来说明我的情况:

#! /usr/bin/perl
use strict;
use warnings;
use Parallel::ForkManager;

my $nlines = `wc -l $input`;
chomp($nlines);
my $ncores = `nproc`;
chomp($ncores);
system( "split -n $ncores $input out_" ); # files are named out_aa, out_ab, etc.
my $pm = new Parallel::ForkManager($ncores);

# declare and initialize
our @data;
for(my $i=0;$i<$nlines;$i++) {
  $data[$i]=0;
}

my $string = "string_literal"; # basis for filtering input data
my @files = <out_*>;
foreach my $file (@files) {
  my $pid = $pm->start and next;
  open(my $FH,"-|","grep -n $string $file");
  while(<$FH>) {
   chomp();
   my ($lineNumber, $datum) = split(/:/,$_);
   $data[$lineNumber]=$datum;
  }
  close($FH);
  $pm->finish;
}
$pm->wait_all_children;
## concatenate arrays here? ##

从这段代码片段可以看出,我创建了一个数组($data),其长度设置等于输入文本文件中的行数,并将数组的每个元素初始化为零。然后我读取文本文件(由grep -n过滤)并将每行中的数据放在数组中适当编号的元素中(因此,我得到一个包含所有{{1}的特定值的数组。 } - 无法匹配的行的过滤行和零。

假设我将文件拆分为子文件以进行并行处理,如上所述,在满足grep条件后,最好将数组拆分为子数组以进行最终连接吗?

如果是这样,我认为数组应该是词法范围的循环,以防止与并行进程尝试写入同一块内存相关的任何问题。另外,如果建议使用循环后连接,那么分支进程中的数组是如何引用的?

每个都有相同的名称(wait_all_children),并且可能是分叉进程的本地名称,因此我不清楚它们是如何被解决的。可以将数据写入一些可供所有子进程访问的全局数组(这个考虑促使在上例中的数组声明中使用$data)?

或许,这是XY problem的一个例子,在这种情况下建议使用完全不同的方法(例如,线程)?是使用our命令行实用程序进行文本文件的初始细分,建议将数据分段传递给并行进程,还是另一种(例如,Perl-内在的)数据分区方法是可取的?感谢。

1 个答案:

答案 0 :(得分:1)

当你fork时,每个进程都有自己的内存,并且不共享变量。因此不必担心变量作用域,但父级不能直接看到子进程中变量中的任何数据。

但是Parallel::ForkManager有助于提供将数据传递回父进程的工具,所以我建议你试试。

相关问题