El siguiente ejemplo calcula el número en paralelo lanzando diversos procesos que realizan una suma parcial. El proceso padre recolecta los resultados tan pronto como terminan haciendo uso de IO::Select:
pp2@nereida:~/LGRID_Machine/examples$ cat -n gridpipes.pl 1 #!/usr/bin/perl 2 use warnings; 3 use strict; 4 use IO::Select; 5 use GRID::Machine; 6 use Time::HiRes qw(time gettimeofday tv_interval); 7 8 my @machine = qw{beowulf orion nereida}; 9 my $nummachines = @machine; 10 my %machine; # Hash of GRID::Machine objects 11 #my %debug = (beowulf => 12345, orion => 0, nereida => 0); 12 my %debug = (beowulf => 0, orion => 0, nereida => 0); 13 14 my $np = shift || $nummachines; # number of processes 15 my $lp = $np-1; 16 17 my $N = shift || 100; 18 19 my @pid; # List of process pids 20 my @proc; # List of handles 21 my %id; # Gives the ID for a given handle 22 23 my $cleanup = 0; 24 25 my $pi = 0; 26 27 my $readset = IO::Select->new(); 28 29 my $i = 0; 30 for (@machine){ 31 my $m = GRID::Machine->new(host => $_, debug => $debug{$_}, ); 32 33 $m->copyandmake( 34 dir => 'pi', 35 makeargs => 'pi', 36 files => [ qw{pi.c Makefile} ], 37 #cleanfiles => 1, 38 #cleandirs => 1, # remove the whole directory at the end 39 ) 40 unless -x 'pi/pi'; 41 42 die "Can't execute 'pi'\n" unless $m->_x("pi")->result; 43 44 $machine{$_} = $m; 45 last unless $i++ < $np; 46 } 47 48 my $t0 = [gettimeofday]; 49 for (0..$lp) { 50 my $hn = $machine[$_ % $nummachines]; 51 my $m = $machine{$hn}; 52 ($proc[$_], $pid[$_]) = $m->open("./pi $_ $N $np |"); 53 $readset->add($proc[$_]); 54 my $address = 0+$proc[$_]; 55 $id{$address} = $_; 56 } 57 58 my @ready; 59 my $count = 0; 60 do { 61 push @ready, $readset->can_read; 62 my $handle = shift @ready; 63 64 my $me = $id{0+$handle}; 65 66 my ($partial); 67 my $numBytesRead = sysread($handle, $partial, 1024); 68 chomp($partial); 69 70 $pi += $partial; 71 print "Process $me: machine = $machine[$me % $nummachines] partial = $partial pi = $pi\n"; 72 73 $readset->remove($handle) if eof($handle); 74 } until (++$count == $np); 75 76 my $elapsed = tv_interval ($t0); 77 print "Pi = $pi. N = $N Time = $elapsed\n";
Sigue un ejemplo de ejecución:
pp2@nereida:~/src/perl/Event/select$ time pi 0 100000000 1 3.141593 real 0m3.244s user 0m3.244s sys 0m0.000s pp2@nereida:~/src/perl/Event/select$ sshseveralpipes4.pl 1 100000000 Process 0: machine = orion partial = 3.141593 pi = 3.141593 Pi = 3.141593. N = 100000000 Time = 3.46131 pp2@nereida:~/src/perl/Event/select$ sshseveralpipes4.pl 3 100000000 Process 2: machine = nereida partial = 1.047198 pi = 1.047198 Process 1: machine = beowulf partial = 1.047198 pi = 2.094396 Process 0: machine = orion partial = 1.047198 pi = 3.141594 Pi = 3.141594. N = 100000000 Time = 1.927591
Este es el fuente (en C) del programa pi.c
:
pp2@nereida:~/src/perl/Event/select$ cat -n pi.c 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 main(int argc, char **argv) { 5 int id, N, np, i; 6 double sum, left; 7 8 if (argc != 4) { 9 printf("Uso:\n%s id N np\n",argv[0]); 10 exit(1); 11 } 12 id = atoi(argv[1]); 13 N = atoi(argv[2]); 14 np = atoi(argv[3]); 15 for(i=id, sum = 0; i<N; i+=np) { 16 double x = (i + 0.5)/N; 17 sum += 4 / (1 + x*x); 18 } 19 sum /= N; 20 printf("%lf\n", sum);Estos son los contenidos del
Makefile
:
pp2@nereida:~/src/perl/Event/select$ cat -T Makefile pi: ^Icc pi.c -o pi
Casiano Rodríguez León