如何调用单个perl脚本通过循环并行运行不同的输入参数

时间:2013-01-29 14:47:28

标签: perl parallel-processing

我是perl的新手。目前我正在运行一个perl脚本,它将调用另一个perl脚本。第二个perl脚本有2个输入参数

sample2.pl -itest.txt -ffile1.txt

我有-f的{​​{1}}的不同输入参数。

现在我想为所有输入参数(file1,file2,file3)并行运行第二个perl脚本 目前我正在运行 -

file1,file2,file3...file10

但它不是并行运行,而是一个接一个地运行。请帮助平行运行这些脚本。 提前致谢。

5 个答案:

答案 0 :(得分:6)

您需要创建一个新进程并将其从主程序中分离出来。您可以徒步with fork执行此操作,但也可以使用Parallel::ForkManager执行此操作。它会照顾你的一切。

use strict; use warnings;
use Parallel::ForkManager;

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

open (my $fh, '<', "output3.txt") or die $!;
while (my $data = <$fh>) {
  chomp $data;

  # Forks and returns the pid for the child:
  my $pid = $pm->start and next;

  # we are now in the child process
  print system ("perl ucm3.pl -iinput.txt -f$data ");

  $pm->finish; # Terminates the child process
}

修改:如果您还不熟悉Perl,请查看this manual。它将告诉您如何从CPAN获取Parallel :: FormManager(和其他东西)。

答案 1 :(得分:1)

除了给出的其他好答案之外,您还应该考虑重新设计,这样就不会使用system来为每个进程启动一个新的Perl实例。

启动所有这些perl会增加开销(如果您尝试使用并行处理加速,那么这可能是您关心的事情。)

理想情况下,您可以将ucm3.pl放入可以从主程序中调用的模块中。

但是对于快速破解解决方案,您可以将整个文件包装在子例程调用中:

sub ucm3
{
    #a trick to make the sub arguments look like program arguments.
    local @ARGV = @_;

    [ rest of the ucm3.pl file in here. ]

}

现在,在您的程序中,包含文件:

require 'ucm3.pl';

而不是你的系统调用,你可以这样做:

ucm3("-iinput.txt", "-f$_");

与其他答案中建议的forkthreads结合使用。

更新:,因为您每次都使用相同的“input.txt”文件,您可以通过重构代码来进一步提高效率,以便“input.txt”仅处理一次。如果该文件很大,则尤其如此。

答案 2 :(得分:0)

对于并行处理,您可以使用threads。 可以研究文档here

答案 3 :(得分:0)

如果您正在使用类似Unix的系统,那么您可以进行系统调用,并放置一个&amp;在系统命令的末尾:

system "perl ucm3.pl -iinput.txt -f$_ &"

答案 4 :(得分:0)

您也可以使用threads和Thread :: Queue执行此操作。它比Parallel :: ForkManager更冗长,但它易于管理,可以轻松修改以捕获所有输出并将它们传递到另一个队列。

#!/usr/bin/env perl

use warnings;
use strict;

use threads;
use Thread::Queue;
use contant MAX_THREADS => 10;

# create a queue that we will fill with work
my $q = Thread::Queue->new();

open (my $fh, '<', "output3.txt") or die "cannot open output3.txt $!";
while (my $data = <$fh>) {
  chomp $data;
  # add each file to the queue
  $q->enqueue($data);
}

for (1..MAX_THREADS) {
  # create some faux signals to end work
  $q->enqueue("SIGEXIT");
  # create threads and do work
  threads->create("work");
}

# wait until threads are all done
while (threads->list(threads::running)) {
  sleep 1;
}
print "all done\n";

# subroutine each thread performs
sub work {
  while (my $file = $q->dequeue()) {
    last if $file eq 'SIGEXIT';
    print system ("perl ucm3.pl -iinput.txt -f$file");
  }
  # detach thread for automatic cleanup
  threads->detach;
}