Question

Salut j'ai un script simple qui prend un fichier et exécute un autre script Perl sur elle. Le script fait cela à chaque fichier image dans le dossier en cours. Ceci est en cours d'exécution sur un ordinateur avec deux processeurs Xeon quad core, 16Go de RAM, exécutant RedHat Linux.

La première work.pl de script appelle essentiellement magicplate.pl passe certains paramètres et le nom du fichier pour magicplate.pl à traiter. Plate magique prend environ une minute pour traiter chaque image. Parce que work.pl est préformage la même fonction plus de 100 fois et parce que le système a plusieurs processeurs et de cœurs que je pensais à diviser la tâche de façon à ce qu'il puisse exécuter plusieurs fois en parallèle. Je pourrais diviser les images à différents dossiers si nécessaire. Toute aide est la bienvenue. Merci

Voici ce que j'ai jusqu'à présent:

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");
     }
}       
Était-ce utile?

La solution

Vous pouvez utiliser Parallel :: ForkManager (set MAX_PROCESSES de $ au nombre de dossiers traités en même temps):

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

     }
}       

Mais comme l'a suggéré Hugmeir d'exécuter l'interpréteur perl encore et encore pour chaque nouveau fichier n'est pas une bonne idée.

Autres conseils

Vous devriez considérer ne pas créer un nouveau processus pour chaque fichier que vous voulez processus - Il est terriblement inefficace, et probablement ce qui se passe plus de temps ici. Il suffit de charger jusqu'à Perl et quel que soit les modules que vous utilisez encore et devrait être la création d'une surcharge. Je me souviens d'une affiche sur PerlMonks qui a fait quelque chose de semblable, et a fini par transformer son deuxième script dans un module, ce qui réduit le temps de travail d'une heure à quelques minutes . Non pas que vous devriez vous attendre une telle amélioration spectaculaire, mais on peut rêver ..

Avec le second script refactorisé comme module, est ici un exemple de d'utilisation du fil, en qui BrowserUK crée un pool de threads, alimentant l'emploi grâce à une file d'attente.

  • Importer "maigcplate" et le filetage d'utilisation.
  • magicplate.pl Démarrer en arrière-plan (vous devez ajouter la limitation des processus)
  • Importer "magicplate" et une fourchette d'utilisation (processus add et un étranglement moissonneur Kiddy)
  • Assurez-vous « maigcplate » un démon avec un pool de travailleurs = Nombre de processeurs
    • utiliser une implémentation MQ pour la communication
    • utiliser des prises pour la communication
  • Utilisez serveur Web (nginx, apache, ...) et l'envelopper dans REST pour un webservice
  • etc ...

Tous ces centre autour de la création de travailleurs multiples qui peuvent chaque exécution de leur propre cpu. Certaines implémentations utilisent mieux les ressources (ceux qui ne commencent pas un nouveau processus) et plus faciles à mettre en œuvre et à maintenir.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top