6

嗨,我有一个简单的脚本,它接受一个文件并在其上运行另一个 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");
     }
}       
4

3 回答 3

7

您应该考虑不要为您要处理的每个文件创建一个新进程——它的效率非常低,而且可能是您花费大部分时间的原因。只是加载 Perl 和你一遍又一遍地使用的任何模块应该会产生一些开销。我记得 PerlMonks 上的一张海报做了类似的事情,最终将他的第二个脚本转换为一个模块,将工作时间从一个小时减少到几分钟。并不是说您应该期待如此巨大的进步,而是可以梦想..

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

于 2010-12-13T14:18:19.600 回答
3
  • 导入“maigcplate”并使用线程。
  • 在后台启动 magicplate.pl(您需要添加进程限制)
  • 导入“magicplate”并使用 fork(添加进程限制和小子收割机)
  • 使“maigcplate”成为一个带有工人池的守护进程 = # of CPUs
    • 使用 MQ 实现进行通信
    • 使用套接字进行通信
  • 使用 webserver(nginx, apache, ...) 并在 REST 中包装一个 web 服务
  • ETC...

所有这些都围绕着创建多个工作人员,每个工作人员都可以在自己的 cpu 上运行。某些实现将更好地使用资源(那些不启动新流程的实现)并且更容易实现和维护。

于 2010-12-13T15:03:13.713 回答
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

     }
}       

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

于 2010-12-13T14:23:12.000 回答