Как изменить скрипт 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...

все это сосредоточено вокруг создания нескольких рабочих, которые могут работать каждый на своем собственном процессоре. Некоторые реализации будут лучше использовать ресурсы (те, которые не запускают новый процесс) и будут проще в реализации и обслуживании.