multi-thread : peut-on compter dessus ?

Le
Manuel Pégourié-Gonnard
Bonjour,

Est-ce que de nos jours on peut s'attendre à ce que le Perl présent sur
la plupart des Unix supporte le multi-threading (il me semble que c'est
une option de compilation) ?

Si j'ai bien compris, sous Windows, Perl est toujours compilé en version
multi-thread car c'est ce qui sert à émuler fork(). Sous Unix, je n'ai
pas une expérience assez variée pour savoir sur quoi on peut
raisonnablement compter, je fais donc appel à votre expérience.

Merci,

--
Manuel Pégourié-Gonnard Institut de mathématiques de Jussieu
http://weblog.elzevir.fr/ http://people.math.jussieu.fr/~mpg/
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Jerome Quelin
Le #20594461
Manuel Pégourié-Gonnard wrote:
Si j'ai bien compris, sous Windows, Perl est toujours compilé en version
multi-thread car c'est ce qui sert à émuler fork(). Sous Unix, je n'ai
pas une expérience assez variée pour savoir sur quoi on peut
raisonnablement compter, je fais donc appel à votre expérience.



autant perl n'était pas packagé threadé par les distribs à l'origine, autant
maintenant c'est plus devenu la norme. il faut dire que du temps des threads
perl 5.005 c'était vraiment buggé et plantait souvent.

maintenant avec les ithreads depuis 5.6.x, mais surtout depuis 5.8.x (bcp de
travail de stabilisation, et suppression des anciens threads), les threads
sont plus répandus... avec aussi des applis qui commencent à les utiliser,
dont padre, l'ide perl écrit en perl.

attention toutefois : un perl threadé sera plus lent, et le core perl n'est
pas entièrement thread-safe (typiquement la fonction sort).

concernant les distribs linux :
mandriva : threadé (je le sais, je suis le mainteneur :-) )
fedora : threadé je crois
ubuntu : threadé
debian : threadé sans doute si ubuntu l'est

unix propriétaires : ils en sont encore à perl 5.6 (voire 5.8 au mieux) et
donc ça m'étonnerait qu'ils soient threadés. je ne suis pas au boulot pour
vérifier hpux, solaris ou aix, donc c'est juste une supposition.

cdlt,
jérôme
--

espie
Le #20595021
In article Manuel Pégourié-Gonnard
Bonjour,

Est-ce que de nos jours on peut s'attendre à ce que le Perl présent sur
la plupart des Unix supporte le multi-threading (il me semble que c'est
une option de compilation) ?



Non, on ne peut pas. Pas systematiquement.

Il y a des archis sur lesquelles ca n'a pas ete suffisamment testees, voire
sur lesquelles ca ne marche pas tres bien (vax). Du coup, certains Unix
ont toujours un perl mono-threade... comme OpenBSD (histoire d'avoir un
environnement le plus homogene possible).
Manuel Pégourié-Gonnard
Le #20595271
Marc Espie scripsit :

In article Manuel Pégourié-Gonnard
Bonjour,

Est-ce que de nos jours on peut s'attendre à ce que le Perl présent sur
la plupart des Unix supporte le multi-threading (il me semble que c'est
une option de compilation) ?



Non, on ne peut pas. Pas systematiquement.



Ok.

Il y a des archis sur lesquelles ca n'a pas ete suffisamment testees, voire
sur lesquelles ca ne marche pas tres bien (vax). Du coup, certains Unix
ont toujours un perl mono-threade... comme OpenBSD (histoire d'avoir un
environnement le plus homogene possible).



Merci pour ces précisions.

--
Manuel Pégourié-Gonnard Institut de mathématiques de Jussieu
http://weblog.elzevir.fr/ http://people.math.jussieu.fr/~mpg/
espie
Le #20595551
In article Manuel Pégourié-Gonnard
Marc Espie scripsit :

In article Manuel Pégourié-Gonnard
Bonjour,

Est-ce que de nos jours on peut s'attendre à ce que le Perl présent sur
la plupart des Unix supporte le multi-threading (il me semble que c'est
une option de compilation) ?



Non, on ne peut pas. Pas systematiquement.



Ok.

Il y a des archis sur lesquelles ca n'a pas ete suffisamment testees, voire
sur lesquelles ca ne marche pas tres bien (vax). Du coup, certains Unix
ont toujours un perl mono-threade... comme OpenBSD (histoire d'avoir un
environnement le plus homogene possible).



Merci pour ces précisions.



Pour completer ma reponse, ce que tu peux par contre supposer, c'est qu'il
existe des packages, comme POE, que tu pourras installer sur ton perl, de
facon a t'isoler de l'implementation precise au niveau du systeme, et donc
de lancer des choses a cote, sans trop te preoccuper de savoir si c'est
des threads ou autre.

(caveat: je n'ai pratiquement pas joue avec POE. Je ne sais pas si c'est
pratique ou penible).
Jerome Quelin
Le #20595651
Marc Espie wrote:
Pour completer ma reponse, ce que tu peux par contre supposer, c'est qu'il
existe des packages, comme POE, que tu pourras installer sur ton perl, de
facon a t'isoler de l'implementation precise au niveau du systeme, et donc
de lancer des choses a cote, sans trop te preoccuper de savoir si c'est
des threads ou autre.

(caveat: je n'ai pratiquement pas joue avec POE. Je ne sais pas si c'est
pratique ou penible).



poe est un environnement de programmation événementiel, qui permet en effet
de lancer des choses en parallèle.

cependant, il est important de noter qu'il ne s'agit ni de threads, ni de
multi-processus. à tout moment, il n'y a qu'un et un seul thread. c'est du
multitâche coopératif (à la windows 9x ou macos classique).

par contre, si l'application est bien écrite et évite les pièges classiques
où une sub monopolise l'exécution, on peut simuler du multi-threading
facilement. ça reste une simulation.

introduction à poe : http://merlin.mongueurs.net/talks/intro_poe.pdf

cdlt,
jérôme
--

Manuel Pégourié-Gonnard
Le #20595921
Jerome Quelin scripsit :

Marc Espie wrote:
Pour completer ma reponse, ce que tu peux par contre supposer, c'est qu'il
existe des packages, comme POE, que tu pourras installer sur ton perl, de
facon a t'isoler de l'implementation precise au niveau du systeme, et donc
de lancer des choses a cote, sans trop te preoccuper de savoir si c'est
des threads ou autre.

(caveat: je n'ai pratiquement pas joue avec POE. Je ne sais pas si c'est
pratique ou penible).



poe est un environnement de programmation événementiel, qui permet en effet
de lancer des choses en parallèle.



Ok.

Je vais du coup préciser ma question : il s'agit d'une application en
Perl/Tk, qui lance des processus externe dont le temps d'exécution est
assez long, et donne actuellement l'impression de geler complètement en
attendant que le processus externe soit terminé.

Il me semble que Paul avait suggéré à un moment que le multi-threading
était une option pour attaquer ce genre de problèmes. Mais l'application
est censée tourner sur des plateformes variées, d'où ma question.

Est-ce que POE se mêle bien à Tk ?

introduction à poe : http://merlin.mongueurs.net/talks/intro_poe.pdf



Je vais y jeter un oeil.

--
Manuel Pégourié-Gonnard Institut de mathématiques de Jussieu
http://weblog.elzevir.fr/ http://people.math.jussieu.fr/~mpg/
Jerome Quelin
Le #20595911
Manuel Pégourié-Gonnard wrote:
Je vais du coup préciser ma question : il s'agit d'une application en
Perl/Tk, qui lance des processus externe dont le temps d'exécution est
assez long, et donne actuellement l'impression de geler complètement en
attendant que le processus externe soit terminé.



poe est en effet très bien adapté à ceci.
tu voudras sans doute utiliser le module poe::wheel::run qui permet de faire
cela très simplement dans poe.

Il me semble que Paul avait suggéré à un moment que le multi-threading
était une option pour attaquer ce genre de problèmes. Mais l'application
est censée tourner sur des plateformes variées, d'où ma question.

Est-ce que POE se mêle bien à Tk ?



très bien.
poe est justement parfait pour programmer une interface graphique qui doit
aussi faire des accès réseau et d'autres choses à côté... sans poe, c'est
très facile de figer l'appli. (comme tu as pu le constater :-) )

introduction à poe : http://merlin.mongueurs.net/talks/intro_poe.pdf



Je vais y jeter un oeil.



il y a un exemple assez simple de poe+tk

exemples de modules utilisant poe et tk : games::pandemic et games::risk
(j'en suis l'auteur, donc n'hésite pas à poser des questions)

jérôme
--

perlgenome
Le #20599971
Il existe aussi cette article expliquant comment faire une application
en multithread : http://djibril.developpez.com/tutoriels/perl/perlTkThreadP rogressBar/
Ça fonctionne aussi bien.
Sinon Jérôme, j'avais lu la doc sur POE et TK, mais l'exemple ne m'a
pas aidé à comprendre comment vraiment faire du multithread en Tk avec
POE. As tu d'autres exemples de codes pouvant nous aider à l'utiliser.
Par exemple faire 2 boutons dont le clic sur l'un lance une procédure
qui exécute une tache pendant 2 minutes par exemple sans figer
l'application et l'autre lance une commande system également longue.
Le tout sous Windows bien sur.

Merci
Jerome Quelin
Le #20605331
perlgenome wrote:
Sinon Jérôme, j'avais lu la doc sur POE et TK, mais
l'exemple ne m'a pas aidé à comprendre comment vraiment faire du
multithread en Tk avec POE.



encore une fois, ce n'est pas du multithread. c'est du temps partagé
coopératif.

As tu d'autres exemples de codes pouvant nous
aider à l'utiliser. Par exemple faire 2 boutons dont le clic sur l'un
lance une procédure qui exécute une tache pendant 2 minutes par exemple
sans figer l'application et l'autre lance une commande system également
longue. Le tout sous Windows bien sur.



tu crées une session définissant un certain nombre d'événements auquel
réagir (on les verrra plus loin) et ensuite tu lances poe :

#!/usr/bin/env perl
use strict;
use warnings;
use Tk;
use POE;
use POE::Wheel::Run;
POE::Session->create(
inline_states => {
_start => &on_start,
# callback interface
system => &on_system,
internal => &on_internal,
# process externe
got_child_stdout => &got_child_stdout,
got_child_close => &got_child_close,
}
);
POE::Kernel->run;
exit;


le callback de démarrage de ta session va créer l'interface :

sub on_start {
my ($k, $s, $h) = @_[KERNEL, SESSION, HEAP];
$poe_main_window->Button(
-text=>'system',
-command=>$s->postback('system')
)->pack;
$poe_main_window->Button(
-text=>'internal',
-command=>$s->postback('internal')
)->pack;
}

on crée 2 boutons, qui lancent des postbacks - cad des événements à la
session.

le callback pour l'evt system va lancer une wheel qui lancera le programme
de manière asynchrone :

sub on_system {
my $child = POE::Wheel::Run->new(
Program => [ "/bin/ls", "-1", "/" ],
StdoutEvent => "got_child_stdout",
StderrEvent => "got_child_stderr",
CloseEvent => "got_child_close",
);

$_[KERNEL]->sig_child($child->PID, "got_child_signal");
$_[HEAP]{children_by_wid}{$child->ID} = $child;
$_[HEAP]{children_by_pid}{$child->PID} = $child;

print(
"Child pid ", $child->PID,
" started as wheel ", $child->ID, ".n"
);
}

exemple de ce qu'on fait de l'output de la commande externe :
sub on_child_stdout {
my ($stdout_line, $wheel_id) = @_[ARG0, ARG1];
my $child = $_[HEAP]{children_by_wid}{$wheel_id};
print "pid ", $child->PID, " STDOUT: $stdout_linen";
}

ne pas oublier de traper la fin de process du fils :
sub on_child_close {
my $wheel_id = $_[ARG0];
my $child = delete $_[HEAP]{children_by_wid}{$wheel_id};

# May have been reaped by on_child_signal().
unless (defined $child) {
print "wid $wheel_id closed all pipes.n";
return;
}

print "pid ", $child->PID, " closed all pipes.n";
delete $_[HEAP]{children_by_pid}{$child->PID};
}


pour un traitement interne qui prend bcp de temps, on va découper le
traitement en petits lots. chaque lot va s'exécuter, puis rendre la main à
poe, en lançant un événement de continuation. cela permet à poe de schéduler
les évts en attente. en admettant que notre traitement interne doit faire
quelque chose un million de fois, on va faire des lots 100 par 100 :

sub on_internal {
my $h = $_[HEAP];
$h->{i} //= 0; # compte de 0 à 999_999
my $i = 0; # compte de 0 à 99
while ( $i++ < 100 && $h->{i} < 1_000_000 ) {
# ...
$h->{i}++;
}
if ( $h->{i} < 1_000_000 ) {
# on n'a pas fini notre boucle, mais on a fini le lot
# on indique à poe de relancer l'evt on_internal.
$_[KERNEL]->yield('on_internal');
} else {
print "done.n";
}
}

bon bien sûr il faudrait mettre à jour l'interface (empêcher de cliquer à
nouveau sur les boutons), de même que l'initialisation de la grande boucle
sera certainement plus conséquente que ça.

mais tu as les mécanismes de base pour ce que tu souhaites faire.

cdlt,
jérôme
--

perlgenome
Le #20678571
On 22 nov, 11:11, Jerome Quelin
perlgenome wrote:
> Sinon Jérôme, j'avais lu la doc sur POE et TK, mais
> l'exemple ne m'a pas aidé à comprendre comment vraiment faire du
> multithread en Tk avec POE.

encore une fois, ce n'est pas du multithread. c'est du temps partagé
coopératif.

> As tu d'autres exemples de codes pouvant nous
> aider à l'utiliser. Par exemple faire 2 boutons dont le clic sur l'un
> lance une procédure qui exécute une tache pendant 2 minutes par exe mple
> sans figer l'application et l'autre lance une commande system égaleme nt
> longue. Le tout sous Windows bien sur.

tu crées une session définissant un certain nombre d'événements a uquel
réagir (on les verrra plus loin) et ensuite tu lances poe :

#!/usr/bin/env perl
use strict;
use warnings;
use Tk;
use POE;
use POE::Wheel::Run;
POE::Session->create(
  inline_states => {
    _start => &on_start,
    # callback interface
    system => &on_system,
    internal => &on_internal,
    # process externe
    got_child_stdout => &got_child_stdout,
    got_child_close  => &got_child_close,
  }
);
POE::Kernel->run;
exit;

le callback de démarrage de ta session va créer l'interface :

sub on_start {
  my ($k, $s, $h) = @_[KERNEL, SESSION, HEAP];
  $poe_main_window->Button(
        -text=>'system',
        -command=>$s->postback('system')
  )->pack;
  $poe_main_window->Button(
        -text=>'internal',
        -command=>$s->postback('internal')
  )->pack;

}

on crée 2 boutons, qui lancent des postbacks - cad des événements à la
session.

le callback pour l'evt system va lancer une wheel qui lancera le programm e
de manière asynchrone :

sub on_system {
           my $child = POE::Wheel::Run->new(
             Program => [ "/bin/ls", "-1", "/" ],
             StdoutEvent  => "got_child_stdout",
             StderrEvent  => "got_child_stderr",
             CloseEvent   => "got_child_close",
           );

           $_[KERNEL]->sig_child($child->PID, "got_child_sign al");
           $_[HEAP]{children_by_wid}{$child->ID} = $child;
           $_[HEAP]{children_by_pid}{$child->PID} = $child;

           print(
             "Child pid ", $child->PID,
             " started as wheel ", $child->ID, ".n"
           );

}

exemple de ce qu'on fait de l'output de la commande externe :
sub on_child_stdout {
           my ($stdout_line, $wheel_id) = @_[ARG0, ARG1];
           my $child = $_[HEAP]{children_by_wid}{$wheel_id} ;
           print "pid ", $child->PID, " STDOUT: $stdout_line n";

}

ne pas oublier de traper la fin de process du fils :
sub on_child_close {
           my $wheel_id = $_[ARG0];
           my $child = delete $_[HEAP]{children_by_wid}{$wh eel_id};

           # May have been reaped by on_child_signal().
           unless (defined $child) {
             print "wid $wheel_id closed all pipes.n";
             return;
           }

           print "pid ", $child->PID, " closed all pipes.n";
           delete $_[HEAP]{children_by_pid}{$child->PID};

}

pour un traitement interne qui prend bcp de temps, on va découper le
traitement en petits lots. chaque lot va s'exécuter, puis rendre la mai n à
poe, en lançant un événement de continuation. cela permet à poe d e schéduler
les évts en attente. en admettant que notre traitement interne doit fai re
quelque chose un million de fois, on va faire des lots 100 par 100 :

sub on_internal {
        my $h = $_[HEAP];
        $h->{i} //= 0;  # compte de 0 à 999_999
        my $i = 0;      # compte de 0 à 99
        while ( $i++ < 100 && $h->{i} < 1_000_000 ) {
                # ...
                $h->{i}++;
        }
        if ( $h->{i} < 1_000_000 ) {
                # on n'a pas fini notre boucle, mais on a fini le lot
                # on indique à poe de relancer l'evt on _internal.
                $_[KERNEL]->yield('on_internal');
        } else {
                print "done.n";
        }

}

bon bien sûr il faudrait mettre à jour l'interface (empêcher de cli quer à
nouveau sur les boutons), de même que l'initialisation de la grande bou cle
sera certainement plus conséquente que ça.

mais tu as les mécanismes de base pour ce que tu souhaites faire.

cdlt,
jérôme
--




Je n'arrive pas à installer tes modules tk : games::pandemic et
games::risk sous Windows. Il ne sont présent dans aucun des
repositories.
Publicité
Poster une réponse
Anonyme