From a529020127dadf5a262aa12916d3cef5e77f1949 Mon Sep 17 00:00:00 2001 From: Alex Gough Date: Mon, 6 Jun 2011 04:01:09 +0100 Subject: [PATCH] README generated from pod2text Simple.pm --- README | 282 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 282 insertions(+) create mode 100644 README diff --git a/README b/README new file mode 100644 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. + -- 2.39.5