Как я могу изменить мой сценарий Perl, чтобы использовать несколько процессоров?

StackOverflow https://stackoverflow.com/questions/4429544

Вопрос

Привет, у меня есть простой скрипт, который принимает файл и запускает другой сценарий Perl на нем. Сценарий делает это на каждый файл изображения в текущей папке. Это работает на машине с 2 четырехъядерными процессорами Xeon, 16 ГБ оперативной памяти, работает Redhat Linux.

Первый сценарий Work.pl в основном вызывает magicplate.pl проходит некоторые параметры и имя файла для magicplate.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 и какие бы модули, которые вы используете снова и снова должны создавать накладные расходы. Я вспоминаю плакат на перлмонксах, которые делали что-то подобное и закончили преобразовывать свой второй скрипт в модуль, уменьшая рабочее время от часа до нескольких минут. Отказ Не то чтобы вы должны ожидать такого драматического улучшения, но можно мечтать ..

Со втором сценарием, рекактором как модуль, Вот пример использования потоков, в котором браурек создает пул резьбы, кормит его задания через очередь.

  • Импортировать «Maigcplate» и использовать резьбу.
  • Запустите Magic Plass.pl на заднем плане (вам нужно будет добавить процесс дросселирования)
  • Импортировать «MIGHTPLATE» и использовать вилку (добавить процесс дроссели и детский жнец)
  • Сделать «Maigcplate» демон с бассейном рабочих = # CPU
    • Используйте реализацию MQ для связи
    • Используйте розетки для связи
  • Используйте веб-сервер (NGINX, APACHACH, ...) и Wrap в покое для веб-сайта
  • и т.д...

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top