--- /dev/null
+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.
+