This chapter can be safely ignored on a first reading, and maybe permanently. It is for application programmers who wish to develop their own low-level message-based parallel application. The additional UNIX system calls in ParGAP may also be useful in some applications.
This section lists some of the more common message passing commands, followed by a short MPI example. The next section (Other low level commands) contains more (but by no means all) of the MPI commands and some UNIX system calls. The ParGAP binding provides a simplified form that makes interactive usage easier. This section describes the original MPI binding in C, with some comments about the interactive versions provided in ParGAP. (The MPI standard includes a binding both to C and to FORTRAN.)
Even if your ultimate goal is a standalone  C-based  application,  it  is
useful to prototype your application with  equivalent  commands  executed
interactively within ParGAP. Note that this  distribution  includes  a
subdirectory mpinu, which provides a  subset  MPI  implementation  in C
with a small footprint. It consists of a C library, libmpi.a, and  an
include  file  mpi.h.  The  library  is   approximately   150 KB.   The
subdirectory can be consulted for further details.
We first briefly explain some MPI concepts.
QUIT_TAG, an INTEGER_ARRAY_TAG, START_TASK2_TAG, etc. In  fact,
    our  implementation  of  the  Slave  Listener   and   MasterSlave()
    specifically uses certain tags of value 1000  and  higher  for  these
    purposes.  Hence,  application  routines  that  do  use  tags  should
    restrict themselves to tags [0..999].
MPI_COMM_WORLD.  The
    ParGAP implementation always  assumes  that  single  namespace.  A
    namespace is important in MPI to build modules and library  routines,
    so that a thread may distinguish messages meant  for  itself,  or  to
    catch errors of cross-communication between two modules.
MPI_COMM_WORLD,  and  topology  is  the   fully
    connected topology.
MPI_Iprobe, and sends can  be
    blocking or not, according to the default underlying sockets).
mpinu  directory)  does  provide  some  commands   for
    collective communication. Examples of  MPI  collective  communication
    commands are MPI_Bcast (broadcast), MPI_Gather  (place  an  entry
    from each  process  in  an  array  residing  on  the  root  process),
    MPI_Scatter  (inverse   of   gather),   MPI_Reduce   (execute   a
    commutative, associative function with an entry from each process and
    store on root; example functions are sum, and, xor, etc.
Here is a short extract of MPI code to illustrate its flavor. It illustrates the C equivalents of the following ParGAP commands. Note that the ParGAP versions noted here take fewer parameters than their C-based cousins, and ParGAP includes defaults for some optional parameters.
MPI_Init() [ called for you automatically when ParGAP is loaded ] F
MPI_Finalize() [ called for you automatically when GAP quits ] F
MPI_Comm_rank() F
MPI_Get_count() F
MPI_Get_source() F
MPI_Get_tag() F
MPI_Comm_size() F
MPI_Send( string buf, int dest[, int tag = 0 ] ) F
MPI_Recv( string buf [, int source = MPI_ANY_SOURCE[, int tag = MPI_ANY_TAG ]  ] ) F
MPI_Probe( [ int source = MPI_ANY_SOURCE[, int tag = MPI_ANY_TAG ] ] ) F
Many  of  the  above  commands  have  analogues  at  a  higher  level  in
section Slave    Listener     Commands     as     GetLastMsgSource(),
GetLastMsgTag(), MPI_Comm_size() = TOPCnumSlaves  +  1,  SendMsg(),
RecvMsg() and ProbeMsg().
#include <stdlib.h>
#include <mpi.h>
#define MYCOUNT 5
#define INT_TAG 1
main( int argc, char *argv[] )
{
  int myrank;
  MPI_Init( &argc, &argv );
  MPI_Comm_rank( MPI_COMM_WORLD, &myrank );
  if ( myrank == 0 ) {
    int mysize, dest, i;
    int buf;
    printf("My rank (master):  %d\n", myrank);
    for ( i=0; i<MYCOUNT; i++ )
      buf = 5;
    MPI_Comm_size( MPI_COMM_WORLD, &mysize );
    printf("Size:  %d\n", mysize);
    for ( dest=1; dest< mysize; dest++ )
      MPI_Send( &buf, MYCOUNT, MPI_INT, dest, INT_TAG, MPI_COMM_WORLD );
  } else {
    int i;
    MPI_Status status;
    int source;
    int count;
    int *buf;
    printf("My rank (slave):  %d\n", myrank);
    MPI_Probe( MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status );
    printf( "Message pending with rank %d and tag %d.\n",
            status.MPI_SOURCE, status.MPI_TAG );
    if ( status.MPI_TAG != INT_TAG )
      printf("Error: Bad tag.\n"); exit(1);
    MPI_Get_count( &status, MPI_INT, &count );
    printf( "The count of how many data units (MPI_INT) is:  %d.\n", count );
    buf = (int *)malloc( count * sizeof(int) );
    source = status.MPI_SOURCE;
    MPI_Recv( buf, count, MPI_INT, source, INT_TAG, MPI_COMM_WORLD, &status );
    for ( i=0; i<MYCOUNT; i++ )
      if ( *buf != 5 ) printf("error:  buf[%d] != 5\n", i);
    printf("slave %d done.\n", myrank);
    }
  MPI_Finalize();
  exit(0);
}
Even in this simplistic example, it was important to specify
MPI_Recv( buf, count, MPI_INT, source, INT_TAG, MPI_COMM_WORLD, &status );
and not to use MPI_ANY_SOURCE instead of  the  known  source.  Although
this alternative would often work, there is a danger that there might  be
a second incoming message from a different source  that  arrives  between
the calls to MPI_Probe() and MPI_Recv(). In such an event, MPI  would
be free to receive the second message in MPI_Recv(),  even  though  the
appropriate count of the second message is likely to be  different,  thus
risking an overflow of the buf buffer.
Other typical bugs in MPI programs are:
MPI_Recv() while no process has  yet  reached  code  that  executes
    MPI_Send().
MPI_Send( buf, count, datatype, dest, tag, COMM_1 ); MPI_Bcast( buffer, count, datatype, root, COMM_2 );
MPI_Bcast( buffer, count, datatype, root, COMM_2 ); MPI_Recv( buf, count, datatype, dest, tag, COMM_1, status );
MPI_Send() is blocking (as  is  the  case  for  long
    messages in the case of many implementations), then the first process
    will block at MPI_Send() while the second blocks at  'MPI_Bcast()'.
    This happens even though they use  distinct  communicators,  and  the
    send-receive communication  would  not  normally  interact  with  the
    broadcast communication.
Much of the TOP-C method in ParGAP (see chapters Basic  Concepts  for the TOP-C model (MasterSlave) and MasterSlave Tutorial) was  developed
precisely to make errors like those above syntactically  impossible.  The
slave listener layer also does some additional work to keep track of  the
status that was last received and other bookkeeping. Additionally,  the
TOP-C method was  designed  to  provide  a  higher  level,  task-oriented
``language'', which would naturally lead the application programmer  into
designing an efficient high level algorithm.
Here is a complete listing of the low level commands available in ParGAP. Some of these commands were documented elsewhere. The remaining ones are not recommended for most users. Nevertheless, it may be useful to others for more sophisticated applications.
For most of these commands, the source code is the ultimat documentation.
However, you may be able to guess at the meaning of many of them based on
their names and their similarity  UNIX  system  calls  (in  the  case  of
UNIX_...) or MPI commands (in  the  case  of  MPI...).  Some  of  the
commands will also show you their calling parameters if called  with  the
wrong number of arguments. Many  of  the  MPI  commands  have  simplified
calling parameters with certain arguments optional or  set  to  defaults,
making them easier for interactive use.
UNIX_MakeString( len ) F
UNIX_DirectoryCurrent() [ Defined in `pkg/pargap/lib/slavelist.g ] F
UNIX_Chdir( string ) F
UNIX_FflushStdout() F
UNIX_Catch( function, return_val ) F
UNIX_Throw() F
UNIX_Getpid() F
UNIX_Hostname() F
UNIX_Alarm( seconds ) F
UNIX_Realtime() F
UNIX_Nice( priority ) F
UNIX_LimitRss( bytes_of_ram ) [ = setrlimit(RLIMIT_RSS, ...) ] F
MPI_Init() F
MPI_Initialized() F
MPI_Finalize() F
MPI_Comm_rank() F
MPI_Get_count() F
MPI_Get_source() F
MPI_Get_tag() F
MPI_Comm_size() F
MPI_World_size() F
MPI_Error_string( errorcode ) F
MPI_Get_processor_name() F
MPI_Attr_get( keyval ) F
MPI_Abort( errorcode ) F
MPI_Send( string buf, int dest[, int tag = 0 ] ) F
MPI_Recv( string buf [, int source = MPI_ANY_SOURCE[, int tag = MPI_ANY_TAG ] ] ) F
MPI_Probe( [ int source = MPI_ANY_SOURCE[, int tag = MPI_ANY_TAG ] ] ) F
MPI_Iprobe( [ int source = MPI_ANY_SOURCE[, int tag = MPI_ANY_TAG ] ] ) F
MPI_ANY_SOURCE V
MPI_ANY_TAG V
MPI_COMM_WORLD V
MPI_TAG_UB V
MPI_HOST V
MPI_IO V
[Up] [Previous] [Next] [Index]
ParGAP manual