如何修改我的perl脚本以使用多个处理器?
-
09-10-2019 - |
题
嗨,我有一个简单的脚本,该脚本获取文件并在其上运行另一个perl脚本。该脚本对当前文件夹中的每个图片文件都这样做。这是在带有2个四核Xeon处理器的机器上运行的,即16GB RAM,运行RedHat Linux。
第一个脚本work.pl基本上调用魔术plate.pl传递一些参数,并将魔术plate.pl的文件名进行处理。魔术板大约需要一分钟来处理每个图像。因为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");
}
}
解决方案
您可以使用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解释器所建议的那样,这不是一个好主意。
其他提示
您应该考虑不要为要处理的每个文件创建一个新的过程 - 这是可怕的效率,并且可能花费大部分时间在这里。只需加载Perl,您一遍又一遍地使用的任何模块都应该创建一些开销。我记得在Perlmonks上做类似事情的海报,最终将他的第二个剧本转换为模块,将工作时间从一个小时减少到几个小时 分钟. 。并不是说您应该期待如此巨大的改进,而是一个人可以做梦。
第二个脚本被重构为模块, 这是线程使用的示例, ,其中Browseruk创建了一个线程池,通过队列为其提供作业。
- 导入“ MAIGCPLATE”并使用线程。
- 在背景中启动魔术plate.pl(您需要添加进程节流)
- 导入“魔术板”并使用叉(添加过程节流和一个小的收割者)
- 使“ Maigcplate”具有工人库= CPU#的守护程序
- 使用MQ实施进行通信
- 使用插座进行通信
- 使用WebServer(nginx,apache,...),并在REST中包装为Web服务
- ETC...
所有这些都围绕创建多个工人,每个工人都可以按自己的CPU运行。某些实现将更好地使用资源(那些未启动新过程的资源),并且更易于实施和维护。
不隶属于 StackOverflow