如何修改perl脚本以使用多个处理器?

Alo*_*los 6 linux perl multithreading file multiprocessor

嗨,我有一个简单的脚本,它接受一个文件,并在其上运行另一个Perl脚本.该脚本对当前文件夹中的每个图片文件执行此操作.这是在一台配备2个四核Xeon处理器,16GB内存,运行RedHat Linux的机器上运行的.

第一个脚本work.pl基本上调用magicplate.pl传递一些参数和magicplate.pl文件的名称来处理.Magic Plate需要大约一分钟来处理每个图像.因为work.pl正在执行相同的功能超过100次,并且因为系统有多个处理器和核心,所以我正在考虑将任务拆分,以便它可以并行运行多次.如有必要,我可以将图像分割到不同的文件夹.任何帮助都会很棒.谢谢

这是我到目前为止:

use strict;
use warnings;


my @initialImages = <*>;

foreach my $file (@initialImages) {

    if($file =~ /.png/){
        print "processing $file...\n";
        my @tmp=split(/\./,$file);
        my $name="";
        for(my $i=0;$i<(@tmp-1);$i++) {
            if($name eq "") { $name = $tmp[$i]; } else { $name=$name.".".$tmp[$i];}
        }

        my $exten=$tmp[(@tmp-1)];
        my $orig=$name.".".$exten;

        system("perl magicPlate.pl -i ".$orig." -min 4 -max 160 -d 1");
     }
}       
Run Code Online (Sandbox Code Playgroud)

Hug*_*eir 7

您应该考虑不为要处理的每个文件创建一个新进程 - 这非常低效,而且可能需要花费大部分时间在这里.只是加载Perl和你一遍又一遍使用的任何模块应该会产生一些开销.我记得PerlMonks上的一张海报做了类似的事情,最后将他的第二个脚本转换成了一个模块,将工作时间从一小时缩短到几分钟.并不是说你应该期待如此显着的改善,但人们可以梦想......

将第二个脚本重构为模块,这是一个线程使用示例,其中BrowserUK创建一个线程池,通过队列为其提供作业.

  • 启动一个新的perl解释器是非常低效的,但使用fork()创建一个新进程非常快(特别是因为Linux使用CoW). (5认同)
  • 不会.如果您的工作将占用1分钟的CPU时间,那么启动新任务所花费的时间将相当微不足道.Perl可能会使用1秒的CPU来启动它的环境(如果你加载了很多模块;我已经看过了),但在那之后,它就是你的全部.仔细阅读问题. (2认同)

gan*_*ass 3

您可以使用 Parallel::ForkManager (将 $MAX_PROCESSES 设置为同时处理的文件数):

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

my @initialImages = <*>;

foreach my $file (@initialImages) {

    if($file =~ /.png/){
        print "processing $file...\n";
        my @tmp=split(/\./,$file);
        my $name="";
        for(my $i=0;$i<(@tmp-1);$i++) {
            if($name eq "") { $name = $tmp[$i]; } else { $name=$name.".".$tmp[$i];}
        }

        my $exten=$tmp[(@tmp-1)];
        my $orig=$name.".".$exten;

  $pm = new Parallel::ForkManager($MAX_PROCESSES);
    my $pid = $pm->start and next;
        system("perl magicPlate.pl -i ".$orig." -min 4 -max 160 -d 1");
    $pm->finish; # Terminates the child process

     }
}       
Run Code Online (Sandbox Code Playgroud)

但正如 Hugmeir 所建议的那样,为每个新文件一次又一次地运行 perl 解释器并不是一个好主意。

  • “为每个新文件一次又一次地运行 perl 解释器不是一个好主意” - 是的,但是当你 fork 时,你并没有启动一个新的 perl 解释器。Fork 复制父进程,而 Linux 使用 CoW,因此它甚至比完整复制更便宜。 (2认同)
  • 另外,为什么你在分叉后要开始一个新的解释器?在新的子进程中运行 perl 代码。 (2认同)