如何并行运行 perl 脚本

Yas*_*ash 3 parallel-processing perl

如何每次都使用不同的输入参数并行运行 perl 脚本:

插图:

perl example.pl param1 param2
perl example.pl param3 param4
Run Code Online (Sandbox Code Playgroud)

我想example.pl用不同的输入运行 perl 脚本2 次或更多次paramsX。每次它都应该并行运行。

示例算法如下:

my $params='1,2,3,4,5';   
my @all_params = split(/\;/, $params);
foreach my $entry (@all_param)
    {
      perl example.pl $entry
    }
Run Code Online (Sandbox Code Playgroud)

我想为每个循环并行运行 perl 脚本。

Sob*_*que 5

你问的事情看起来很简单,但实际上比看起来要复杂得多。

在 perl 中并行化并不太难,但是......这里是龙。当您的程序变得不确定时,并行代码会引入一组全新的错误和竞争条件。您无法再可靠地知道执行顺序。(如果你假设你这样做,你会创建一个竞争条件)。

但是考虑到这一点 - 真的有 3 种(ish?)方法可以解决。

叉子

用Parallel::ForkManager叉子把你的内环包起来。这对于“简单”并行非常有效,但是在您的分叉之间进行通信很困难。

#!/usr/bin/env perl

use strict;
use warnings;

use Parallel::ForkManager;

my $manager = Parallel::ForkManager->new(2);    #2 concurrent

my $params = '1,2,3,4,5';
my @all_params = split( /,/, $params );

foreach my $entry (@all_param) {
   $manager->start and next;
   #your code to run in parallel here;
   print $entry;
   $manager->finish;
}
Run Code Online (Sandbox Code Playgroud)

你可以自己滚动使用,fork但你可能会因为这样做而绊倒。Parallel::ForkManager工作的工具也是如此。

线:

#!/usr/bin/env perl

use strict;
use warnings;

use threads;
use Thread::Queue

  my $work_q = Thread::Queue->new;

sub worker {
   while ( my $item = $work_q->dequeue ) {
      print $item, "\n";
   }
}

my $params = '1,2,3,4,5';
my @all_params = split( /,/, $params );
$work_q->enqueue(@all_params);
$work_q->end;

threads->create( \&worker ) for 1 .. 2;    #2 in parallel
foreach my $thr ( threads->list ) {
   $thr->join;
}
Run Code Online (Sandbox Code Playgroud)

如果您需要做更多的 IPC,这更合适 - 线程通常更适合(IMO)。但是,您不应该将线程视为轻量级(如 fork),因为尽管您可能从其他语言中想到 - perl 线程并不能像那样工作。

使用 IO::Select 和多次open调用来并行化:

#!/usr/bin/env perl

use strict;
use warnings;

use IO::Select; 

my $params = '1,2,3,4,5';
my @all_params = split( /,/, $params );

foreach my $param ( @all_params ) { 
   open ( my $io, '-|', "program_name $param" ); 
   $select -> add ( $io ); 
}

while ( my $fh = $select -> can_read ) { 
   my $line = <$fh>;
   print $line; 
}      
Run Code Online (Sandbox Code Playgroud)

您可以通过IPC::Run2打开 STDIN 和 STDERR 的文件描述符来执行类似的操作。

我是不是该?

并行代码不是灵丹妙药。它的作用是减少“块”并让您消耗资源。如果您的限制资源是 CPU,并且您有 10 个 CPU,那么并行使用 10 个会加快您的速度。

...但如果您的限制资源是 IO - 网络或磁盘带宽 - 它通常无济于事,因为争用实际上会使问题变得更糟。特别是磁盘控制器已经非常有效地并行化、预取和缓存,因此并行访问它们的收益通常很小。


Mar*_*ell 5

没有真正需要编写任何代码(Perl 或其他方式)来并行运行脚本,您可以只使用GNU Parallel并控制一次运行的数量、脚本运行的不同服务器数量以及结果的去向以及关于任何其他方面。

因此,如果您有一个名为的文件params.txt,其中包含:

param1 param2
param3 param4
Run Code Online (Sandbox Code Playgroud)

您可以在终端中执行此操作:

parallel -a params.txt perl {1} {2}
Run Code Online (Sandbox Code Playgroud)

如果你想要一个进度条,只需添加--bar:

parallel --bar ...
Run Code Online (Sandbox Code Playgroud)

如果您想一次运行 8 个:

parallel -j 8 ...
Run Code Online (Sandbox Code Playgroud)

如果你想看看它会做什么而不实际做任何事情:

parallel --dry-run ...
Run Code Online (Sandbox Code Playgroud)