Как изменить скрипт perl для использования нескольких процессоров?
Привет у меня есть простой скрипт, который берет файл и запускает другой скрипт на Perl на нем. Сценарий делает это для каждого файла изображения в текущей папке. Это работает на машине с 2 четырехъядерными процессорами Xeon, 16 ГБ ОЗУ, работающими под управлением 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");
}
}
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 снова и снова для каждого нового файла не является хорошей идеей.
вы должны рассмотреть возможность не создавать новый процесс для каждого файла, который вы хотите обработать-это ужасно неэффективно, и, вероятно, то, что занимает большую часть вашего времени здесь. Просто загрузка Perl и любые модули, которые вы используете снова и снова, должны создавать некоторые накладные расходы. Я помню плакат на PerlMonks, который сделал что-то подобное, и в конечном итоге превратил его второй сценарий в модуль, сократив рабочее время с часа до пары минут. Не то, что вы должны ожидать такое резкое улучшение, но можно мечтать..
второй сценарий переработан модуль, вот пример использования потока, в котором BrowserUK создает пул потоков, подавая ему задания через очередь.
- импортировать "maigcplate" и использовать резьбу.
- пуск magicplate.pl в фоновом режиме (вам нужно будет добавить дросселирование процесса)
- импортируйте "magicplate" и используйте вилку (добавьте дросселирование процесса и детский жнец)
- сделать" maigcplate " демоном с пулом рабочих = # процессоров
- используйте реализацию MQ для связи
- используйте сокеты для связи
- использовать веб-сервер(nginx, apache, ...) и оберните в REST для веб-сервиса
- etc...
все это сосредоточено вокруг создания нескольких рабочих, которые могут работать каждый на своем собственном процессоре. Некоторые реализации будут лучше использовать ресурсы (те, которые не запускают новый процесс) и будут проще в реализации и обслуживании.