Как я могу изменить свой Perl-скрипт для использования нескольких процессоров? - PullRequest
6 голосов
/ 13 декабря 2010

Привет, у меня есть простой скрипт, который берет файл и запускает другой скрипт на 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");
     }
}       

Ответы [ 3 ]

7 голосов
/ 13 декабря 2010

Вы должны рассмотреть НЕ создание нового процесса для каждого файла, который вы хотите обработать - это ужасно неэффективно, и, вероятно, что занимает здесь большую часть вашего времени.Просто загрузка Perl и любых модулей, которые вы используете снова и снова, должна создавать некоторые накладные расходы.Я вспоминаю постер на PerlMonks, который делал что-то похожее и в итоге превратил свой второй скрипт в модуль, сократив рабочее время с часа до пары минут .Не то чтобы вы ожидали такого резкого улучшения, но можно мечтать ..

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

3 голосов
/ 13 декабря 2010
  • Импорт "maigcplate" и использование многопоточности.
  • Запустите magicplate.pl в фоновом режиме (вам необходимо добавить регулирование процесса)
  • Импортируйте "magicplate" и используйте fork (добавить удушение процесса и жнец ребенка)
  • Сделать "maigcplate" демоном с пулом рабочих = число процессоров
    • использовать для связи реализацию MQ
    • использовать сокеты длясвязь
  • Использование веб-сервера (nginx, apache, ...) и перенос в REST для веб-службы
  • и т. д. *

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

3 голосов
/ 13 декабря 2010

Вы можете использовать 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-интерпретатор длякаждый новый файл не очень хорошая идея.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...