]> git.donarmstrong.com Git - libparallel-mpi-simple-perl.git/commitdiff
README generated from pod2text Simple.pm
authorAlex Gough <alex@earth.li>
Mon, 6 Jun 2011 03:01:09 +0000 (04:01 +0100)
committerAlex Gough <alex@earth.li>
Mon, 6 Jun 2011 03:01:09 +0000 (04:01 +0100)
README [new file with mode: 0644]

diff --git a/README b/README
new file mode 100644 (file)
index 0000000..f02d51b
--- /dev/null
+++ b/README
@@ -0,0 +1,282 @@
+NAME
+     Parallel::MPI::Simple
+
+SYNOPSIS
+     mpirun -np 2 perl script.pl
+
+     #!perl
+     use Parallel::MPI::Simple;
+     MPI_Init();
+     my $rank = MPI_Comm_rank(MPI_COMM_WORLD);
+     if ($rank == 1) {
+       my $msg = "Hello, I'm $rank";
+       MPI_Send($msg, 0, 123, MPI_COMM_WORLD);
+     }
+     else {
+       my $msg = MPI_Recv(1, 123, MPI_COMM_WORLD);
+       print "$rank received: '$msg'\n";
+     }
+     MPI_Finalise();
+
+INTRODUCTION
+    Perl is not a strongly typed language, Perl does not enforce data
+    structures of a fixed size or dimensionality, Perl makes things easy.
+    Parallel processing solves problems faster and is commonly programmed
+    using a message passing paradigm. Traditional message passing systems
+    are designed for strongly typed languages like C or Fortran, there exist
+    implementations of these for Perl but they concentrate on perfectly
+    mimicing the standards forcing the poor Perl programmer to use strongly
+    typed data despite all his best instincts.
+
+    This module provides a non-compliant wrapper around the widely
+    implemented MPI libraries, allowing messages to consist of arbitarily
+    nested Perl data structures whose size is limited by available memory.
+    This hybrid approach should allow you to quickly write programs which
+    run anywhere which supports MPI (both Beowulf and traditional MPP
+    machines).
+
+Message Passing and Multiprocessing
+    The message passing paradigm is simple and easy to use. Multiple
+    versions of the same program are run on multiple processors (or nodes).
+    Each running copy should call "MPI_Init" to announce that it is running.
+    It can then find out who it is by calling "MPI_Comm_rank" and who else
+    it can talk to by calling "MPI_Comm_size". Using this information to
+    decide what part it is to play in the ensuing computation, it the
+    exchanges messages, or parcels of data, with other nodes allowing all to
+    cooperate.
+
+    Once the computation is finished, the node calls "MPI_Finalize" and
+    exits cleanly, ready to run another day.
+
+    These processes are all copies of the *same* perl script and are invoked
+    using: "mpirun -np [number of nodes] perl script.pl" .
+
+Starting and Stopping a process
+    A process must formally enter and leave the MPI pool by calling these
+    functions.
+
+  MPI_Init
+      MPI_Init()
+
+    Initialises the message passing layer. This should be the first "MPI_*"
+    call made by the program and ideally one of the first things the program
+    does. After completing this call, all processes will be synchronised and
+    will become members of the "MPI_COMM_WORLD" communicator. It is an error
+    for programs invoked with "mpirun" to fail to call "MPI_Init" (not to
+    mention being a little silly).
+
+  MPI_Finalize
+      MPI_Finalize()
+
+    Shuts down the message passing layer. This should be called by every
+    participating process before exiting. No more "MPI_*" calls may be made
+    after this function has been called. It is an error for a program to
+    exit *without* calling this function.
+
+Communicators
+    All processes are members of one or more *communicators*. These are like
+    channels over which messages are broadcast. Any operation involving more
+    than one process will take place in a communicator, operations involving
+    one communicator will not interfere with those in another.
+
+    On calling "MPI_Init" all nodes automatically join the "MPI_COMM_WORLD"
+    communicator. A communicator can be split into smaller subgroups using
+    the "MPI_Comm_split" function.
+
+  MPI_COMM_WORLD
+     $global_comm = MPI_COMM_WORLD;
+
+    Returns the global communicator shared by all processes launched at the
+    same time. Can be used as a "constant" where a communicator is required.
+    Most MPI applications can get by using only this communicator.
+
+  MPI_Comm_rank
+      $rank = MPI_Comm_rank($comm);
+
+    Returns the rank of the process within the communicator given by $comm.
+    Processes have ranks from 0..(size-1).
+
+  MPI_Comm_size
+      $size = MPI_Comm_size($comm);
+
+    Returns the number of processes in communicator $comm.
+
+  MPI_Comm_compare
+        $result = MPI_Comm_compare($comm1, $comm2);
+
+    Compares the two communicators $comm1 and $comm2. $result will be equal
+    to:
+
+      MPI_IDENT    : communicators are identical
+      MPI_CONGRUENT: membership is same, ranks are equal
+      MPI_SIMILAR  : membership is same, ranks not equal
+      MPI_UNEQUAL  : at least one member of one is not in the other
+
+  MPI_Comm_dup
+        $newcomm = MPI_Comm_dup($comm);
+
+    Duplicates $comm but creates a new context for messages.
+
+  MPI_Comm_split
+        $newcomm = MPI_Comm_split($comm, $colour, $key);
+
+    Every process in $comm calls "MPI_Comm_split" at the same time. A new
+    set of communicators is produced, one for each distinct value of
+    $colour. All those processes which specified the same value of $colour
+    end up in the same comminicator and are ranked on the values of $key,
+    with their original ranks in $comm being used to settle ties.
+
+    If $colour is negative (or "MPI_UNDEFINED"), the process will not be
+    allocated to any of the new communicators and "undef" will be returned.
+
+  MPI_Comm_free
+        MPI_Comm_free($comm, [$comm2, ...] );
+
+    Frees the underlying object in communicator $comm, do not attempt to do
+    this to MPI_COMM_WORLD, wise to do this for any other comminicators that
+    you have created. If given a list of comminicators, will free all of
+    them, make sure there are no duplicates...
+
+Communications operations
+  MPI_Barrier
+      MPI_Barrier($comm);
+
+    Waits for every process in $comm to call MPI_Barrier, once done, all
+    continue to execute. This causes synchronisation of processes. Be sure
+    that every process does call this, else your computation will hang.
+
+  MPI_Send
+      MPI_Send($scalar, $dest, $msg_tag, $comm);
+
+    This takes a scalar (which can be an anonymous reference to a more
+    complicated data structure) and sends it to process with rank $dest in
+    communicator $comm. The message also carries $msg_tag as an identfier,
+    allowing nodes to receive and send out of order. Completion of this call
+    does not imply anything about the progress of the receiving node.
+
+  MPI_Recv
+     $scalar = MPI_Recv($source, $msg_tag, $comm);
+
+    Receives a scalar from another process. $source and $msg_tag must both
+    match a message sent via MPI_Send (or one which will be sent in future)
+    to the same communicator given by $comm.
+
+     if ($rank == 0) {
+       MPI_Send([qw(This is a message)], 1, 0, MPI_COMM_WORLD); 
+     }
+     elsif ($rank == 1) {
+       my $msg = MPI_Recv(1,0,MPI_COMM_WORLD);
+       print join(' ', @{ $msg } );
+     }
+
+    Will output "This is a message". Messages with the same source,
+    destination, tag and comminicator will be delivered in the order in
+    which they were sent. No other guarantees of timeliness or ordering can
+    be given. If needed, use "MPI_Barrier".
+
+  MPI_Bcast
+     $data = MPI_Bcast($scalar, $root, $comm);
+
+    This sends $scalar in process $root from the root process to every other
+    process in $comm, returning this scalar in every process. All non-root
+    processes should provide a dummy message (such as "undef"), this is a
+    bit ugly, but maintains a consistant interface between the other
+    communication operations. The scalar can be a complicated data
+    structure.
+
+      if ($rank == 0) { # send from 0
+        my $msg = [1,2,3, {3=>1, 5=>6}  ];
+        MPI_Bcast( $msg, 0, MPI_COMM_WORLD);
+      }
+      else { # everything else receives, note dummy message
+        my $msg = MPI_Bcast(undef, 0, MPI_COMM_WORLD);
+      }
+
+  MPI_Gather
+     # if root:
+     @list = MPI_Gather($scalar, $root, $comm);
+     #otherwise
+     (nothing) = MPI_Gather($scalar, $root, $comm);
+
+    Sends $scalar from every process in $comm (each $scalar can be
+    different, root's data is also sent) to the root process which collects
+    them as a list of scalars, sorted by process rank order in $comm.
+
+  MPI_Scatter
+     $data = MPI_Scatter([N items of data], $root, $comm);
+
+    Sends list of scalars (anon array as 1st arg) from $root to all
+    processes in $comm, with process of rank N-1 receiving the Nth item in
+    the array. Very bad things might happen if number of elements in array
+    != N. This does not call the C function at any time, so do not expect
+    any implicit synchronisation.
+
+  MPI_Allgather
+     @list = MPI_Allgather($scalar, $comm);
+
+    Every process receives an ordered list containing an element from every
+    other process. Again, this is implemented without a call to the C
+    function.
+
+  MPI_Alltoall
+     @list = MPI_Alltoall([ list of scalars ], $comm);
+
+    Simillar to Allgather, each process (with rank *rank*) ends up with a
+    list such that element *i* contains the data which started in element
+    *rank* of process *i*s data.
+
+  MPI_Reduce
+     $value = MPI_Reduce($input, \&operation, $comm);
+
+    Every process receives in $value the result of performing &operation
+    between every processes $input. If there are three processes in $comm,
+    then "$value = $input_0 op $input_1 op $input_2".
+
+    Operation should be a sub which takes two scalar values (the $input
+    above) and returns a single value. The operation it performs should be
+    commutative and associative, otherwise the result will be undefined.
+
+    For instance, to return the sum of some number held by each process,
+    perform:
+
+     $sum = MPI_Reduce($number, sub {$_[0] + $_[1]}, $comm);
+
+    To find which process holds the greatest value of some number:
+
+     ($max, $mrank) = @{ MPI_Reduce([$number, $rank],
+                           sub { $_[0]->[0] > $_[1]->[0] ? $_[0] : $_[1]}
+                             , $comm) };
+
+PHILOSOPHY
+    I have decided to loosely follow the MPI calling and naming conventions
+    but do not want to stick strictly to them in all cases. In the interests
+    of being simple, I have decided that all errors should result in the
+    death of the MPI process rather than huge amounts of error checking
+    being foisted onto the module's user.
+
+    Many of the MPI functions have not been implemented, some of this is
+    because I feel they would complicate the module (I chose to have a
+    single version of the Send command, for instance) but some of this is
+    due to my not having finished yet. I certainly do not expect to provide
+    process topologies or inter-communicators, I also do not expect to
+    provide anything in MPI-2 for some time.
+
+ISSUES
+    This module has been tested on a variety of platforms. I have not been
+    able to get it running with the mpich MPI implementation in a clustered
+    environment.
+
+    In general, I expect that most programs using this module will make use
+    of little other than "MPI_Init", "MPI_Send", "MPI_Recv",
+    "MPI_COMM_WORLD", "MPI_Barrier", "MPI_Comm_size", "MPI_Comm_rank" and
+    "MPI_Finalize".
+
+AUTHOR
+      Alex Gough (alex@rcon.org)
+
+COPYRIGHT
+      This module is copyright (c) Alex Gough, 2001.
+
+      You may use and redistribute this software under the Artistic License as
+      supplied with Perl.
+