GRID-Machine

 view release on metacpan or  search on metacpan

lib/GRID/Machine/Process.pod  view on Meta::CPAN


GRID::Machine::Process - Forking via SSH 

=head1 SYNOPSIS

     use GRID::Machine;
     
     my $host = $ENV{GRID_REMOTE_MACHINE};
     my $machine = GRID::Machine->new( host => $host );
     
     my ($N, $np, $pi)  = (1000, 4, 0);
     for (0..$np-1) {
        $machine->fork( q{
            my ($id, $N, $np) = @_;
              
            my $sum = 0;
            for (my $i = $id; $i < $N; $i += $np) {
                my $x = ($i + 0.5) / $N;
                $sum += 4 / (1 + $x * $x);
            }
            $sum /= $N; 
         },
         args => [ $_, $N, $np ],
       );
     }
     
     $pi += $machine->waitall()->result for 1..$np;
     
     print "pi = $pi\n";


=head1 DESCRIPTION


=head2 The C<fork> method

The C<fork> method of C<GRID::Machine> objects can be used to fork a process in the remote machine,
as shown in the following example:

  $ cat -n fork5.pl 
     1  #!/usr/bin/perl -w
     2  use strict;
     3  use GRID::Machine;
     4  use Data::Dumper;
     5  
     6  my $host = $ENV{GRID_REMOTE_MACHINE};
     7  my $machine = GRID::Machine->new( host => $host );
     8  
     9  my $p = $machine->fork( q{
    10  
    11     print "stdout: Hello from process $$. args = (@_)\n";
    12     print STDERR "stderr: Hello from process $$\n";
    13  
    14     use List::Util qw{sum};
    15     return { s => sum(@_), args => [ @_ ] };
    16   },
    17   args => [ 1..4 ],
    18  );
    19  
    20  # GRID::Machine::Process objects are overloaded
    21  print "Doing something while $p is still alive  ...\n" if $p; 
    22  
    23  my $r = $machine->waitpid($p);
    24  
    25  print "Result from process '$p': ",Dumper($r),"\n";
    26  print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";


When executed, the former program produces an output similar to this:

  $ perl fork5.pl 
  Doing something while 5220:5230:some.machine:5234:5237 is still alive  ...
  Result from process '5220:5230:some.machine:5234:5237': $VAR1 = bless( {
                   'machineID' => 0,
                   'stderr' => 'stderr: Hello from process 5237
  ',
                   'descriptor' => 'some.machine:5234:5237',
                   'status' => 0,
                   'waitpid' => 5237,
                   'errmsg' => '',
                   'stdout' => 'stdout: Hello from process 5237. args = (1 2 3 4)
  ',
                   'results' => [ { 'args' => [ 1, 2, 3, 4 ], 's' => 10 } ]
                 }, 'GRID::Machine::Process::Result' );

  GRID::Machine::Process::Result objects are overloaded in a string context:
  stdout: Hello from process 5237. args = (1 2 3 4)
  stderr: Hello from process 5237


The C<fork> method returns a L<GRID::Machine::Process> object. The first argument must be a string containing
the code that will be executed by the forked process in the remote machine.
Such code is always called in a list context.
The C<fork> method admits the following arguments:

=over 2

=item * C<stdin>

The name of the file to which C<stdin> will be redirected

=item * C<stdout>

The name of the file to which C<stdout> will be redirected. If not specified a temporary file will be used

=item * C<stderr>

The name of the file to which C<stderr> will be redirected. If not specified a temporary file will be used

=item * C<result>

The name of the file to which the result computed by the child process  will be dumped. If not specified a temporary file will be used

=item * C<args>

The arguments for the code executed by the remote child process

=back

=head2 C<GRID::Machine::Process> objects

L<GRID::Machine::Process> objects have been overloaded. In a string context 
a L<GRID::Machine::Process> object 
produces the concatenation C<hostname:clientPID:remotePID>. 
In a boolean context it returns true if the process is alive and false otherwise.
This way, the execution of line 21 in the program above:

    21  print "Doing something while $p is still alive  ...\n" if $p; 

produces an output like:

  Doing something while 5220:5230:some.machine:5234:5237 is still alive  ...

if the remote process is still alive. The descriptor of the process
C<5220:5230:some.machine:5234:5237>
is a colon separated sequence of five components:

=over 2

=item 1 - The PID of the local process executing L<GRID::Machine> 

=item 2 - The PID of the local process in charge of the connection with the remote 
machine

=item 3 - The name of the remote machine 

=item 4 - The PID of the remote process executing L<GRID::Machine::REMOTE>

=item 5 - The PID of the child process created by C<fork>

=back

When evaluated in a boolean context, a L<GRID::Machine::Process> returns
1 if it is alive and 0 otherwise.

=head2 The C<waitpid> method

The C<waitpid> method  waits for the L<GRID::Machine::Process> received as first argument 
to terminate. Additional C<FLAGS> as in perl C<waitpid> can be passed as arguments.
It returns a L<GRID::Machine::Process::Result> object, whose attributes contain:


=over 2 

=item * C<stdout>  

A string containing the output to C<STDOUT> of the remote child process

=item * C<stderr>

A string containing the output to C<STDERR> of the remote child process

=item * C<results>

The list of values returned by the child process. The forking code 
is always called in a list context.

=item * C<status>

The value associated with C<$?> as returned by the remote child process.

=item * C<waitpid>

The value returned by the Perl C<waitpid> function when synchronized 
with the remote child process.
It is usually the value is either the C<pid> of the deceased process, or C<-1> 
if there was no such child process.  On some systems, a value of C<0> indicates that
there are processes still running.  

=item * C<errmsg> 

The child error as in C<$@> 

=item * C<machineID>

The logical identifier of the associated L<GRID::Machine>.
By default, 0 if it was the first L<GRID::Machine> created, 1 if it was the second, etc.

=back 

=head2  The C<waitall> method

It is similar to C<waitpid> but instead waits for any child process.

Behaves like the wait(2) system call on your system: it waits
for a child process to terminate and returns 

=over 2

=item * The C<GRID::Machine::Process::Result>
object associated with the  deceased process if it was called via the L<GRID::Machine> 
C<fork> method, or 

=item * The PID of the deceased process if there is no C<GRID::Machine::Process>
associated (it was called using an ordinary C<fork>)

=item * C<-1> if there are no child processes.  
Note that a return value of C<-1> could mean that child processes are
being automatically reaped, as described in perlipc.

=back

See an example:

  $ cat -n wait1.pl 
     1  #!/usr/bin/perl -w
     2  use strict;
     3  use GRID::Machine;
     4  use Data::Dumper;
     5  
     6  my $host = $ENV{GRID_REMOTE_MACHINE};
     7  my $machine = GRID::Machine->new( host => $host );
     8  
     9  my $p = $machine->fork( q{
    10  
    11     print "stdout: Hello from process $$. args = (@_)\n";
    12     print STDERR "stderr: Hello from process $$\n";
    13  
    14     use List::Util qw{sum};
    15     return { s => sum(@_), args => [ @_ ] };
    16   },
    17   args => [ 1..4 ],
    18  );
    19  
    20  # GRID::Machine::Process objects are overloaded
    21  print "Doing something while $p is still alive  ...\n" if $p; 
    22  
    23  my $r = $machine->waitall();
    24  
    25  print "Result from process '$p': ",Dumper($r),"\n";
    26  print "GRID::Machine::Process::Result objects are overloaded in a string context:\n$r\n";

When executed produces:

  $ perl wait1.pl 
  Doing something while 1271:1280:local:1284:1287 is still alive  ...
  Result from process '1271:1280:local:1284:1287': $VAR1 = bless( {
                   'machineID' => 0,
                   'stderr' => 'stderr: Hello from process 1287
  ',
                   'descriptor' => 'local:1284:1287',
                   'status' => 0,
                   'waitpid' => 1287,
                   'errmsg' => '',
                   'stdout' => 'stdout: Hello from process 1287. args = (1 2 3 4)
  ',
                   'results' => [ { 'args' => [ 1, 2, 3, 4 ], 's' => 10 } ]
                 }, 'GRID::Machine::Process::Result' );

  GRID::Machine::Process::Result objects are overloaded in a string context:
  stdout: Hello from process 1287. args = (1 2 3 4)
  stderr: Hello from process 1287

The following example uses the C<fork> method and C<waitall> to 
compute in parallel a numerical approach to the value of the number C<pi>:

  $ cat -n waitpi.pl 
     1  #!/usr/bin/perl -w
     2  use strict;
     3  use GRID::Machine;
     4  
     5  my $host = $ENV{GRID_REMOTE_MACHINE};
     6  my $machine = GRID::Machine->new( host => $host );
     7  
     8  my ($N, $np, $pi)  = (1000, 4, 0);
     9  for (0..$np-1) {
    10     $machine->fork( q{
    11         my ($id, $N, $np) = @_;
    12           
    13         my $sum = 0;
    14         for (my $i = $id; $i < $N; $i += $np) {
    15             my $x = ($i + 0.5) / $N;
    16             $sum += 4 / (1 + $x * $x);
    17         }
    18         $sum /= $N; 
    19      },
    20      args => [ $_, $N, $np ],
    21    );
    22  }
    23  
    24  $pi += $machine->waitall()->result for 1..$np;
    25  
    26  print "pi = $pi\n";

=head2  The C<async> method

The C<async> method it is quite similar to the fork method
but receives as arguments the  name of a L<GRID::Machine> method 
and the arguments for this method.
It executes asynchronously the method. 
It returns a L<GRID::Machine::Process> object.
Basically, the call

            $m->async($subname => @args) 

is equivalent to:



( run in 0.537 second using v1.01-cache-2.11-cpan-39bf76dae61 )