Program hello_mpi.c

In case you're interested in learning the details, here are the roles of all the MPI routines in the above code and the types of parameters involved in each call.


Line 12 Initializing an MPI process

MPI_Init must be the first MPI routine you call in each process. It can only be called once. It establishes an environment necessary for MPI to run. This environment may be customized for any MPI runtime flags provided by the MPI implementation (note that the command line arguments are passed to the C version of this call).

int MPI_Init(int *argc, char ***argv)

Line 13 Finding the number of processes

MPI_Comm_size returns the number of processes within a communicator. A communicator is MPI's mechanism for establishing separate communication universes; (more on this later). Our sample program uses the predefined world communicatorMPI_COMM_WORLD — which includes all your processes. MPI can determine the number of processes because you specify this when you issue the command used to launch MPI programs.

int MPI_Comm_size(MPI_Comm comm, int *size)

Line 14 Finding a process's rank

Rank is used to specify a particular process. It is an integer in the range 0 through (size-1), where size is the number of processes returned by MPI_Comm_size. MPI_Comm_rank returns the calling process's rank in the specified communicator.

It's often necessary for a process to know its own rank. For example, you might want to divide up computational work in a loop among all your processes, with each process handling a subset of the original range of the loop. One way to do this is for each process to use its rank to compute its range of loop indices.

int MPI_Comm_rank(MPI_Comm comm, int *rank)

When we learn about communicators, you will see that a process may belong to more than one communicator, and may have a different rank in each communicator. For now, assume we are only dealing with the predefined world communicator MPI_COMM_WORLD, which consists of all your processes, as illustrated in the sample program.


Line 20 Sending a message

In MPI, there are many flavors of sends and receives. This is one reason why there are more than 125 routines provided in MPI. In our basic set of six calls, we will look at just one type of send and one type of receive.

MPI_Send is a blocking send. This means the call does not return control to your program until the data have been copied from the location you specify in the parameter list. Because of this, you can change the data after the call and not affect the original message. (There are non-blocking sends where this is not the case.)


int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)

The parameters for MPI_Send are:

buf
is the beginning of the buffer containing the data to be sent. For Fortran, this is often the name of an array in your program. For C, it is an address.
count
is the number of elements to be sent (not bytes)
datatype
is the type of data
dest
is the rank of the process which is the destination for the message
tag
is an arbitrary number which can be used to distinguish among messages
comm
is the communicator

Line 23 Receiving a message

Message passing in MPI-1 requires two-way communication. One-sided communication is one of the features added in MPI-2. In two-way communication (point-to-point communication), each time one process sends a message, another process must explicitly receive the message; for every place in your application that you call an MPI send routine, there needs to be a corresponding place where you call an MPI receive routine. Care must be taken to ensure that the send and receive parameters match. This will be discussed in more detail later.

Like MPI_Send, MPI_Recv is blocking. This means the call does not return control to your program until all the received data have been stored in the variable(s) you specify in the parameter list. Because of this, you can use the data after the call and be certain it is all there. (There are non-blocking receives where this is not the case.)


            int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm
            comm, MPI_Status *status)
        

The parameters for MPI_Recv are:

buff
is the beginning of the buffer where the incoming data are to be stored. For Fortran, this is often the name of an array in your program. For C, it is an address.
count
is the number of elements (not bytes) in your receive buffer
datatype
is the type of data
source
is the rank of the process from which data will be accepted (This can be a wildcard, by specifying the parameter MPI_ANY_SOURCE).
tag
is an arbitrary number which can be used to distinguish among messages (This can be a wildcard, by specifying the parameter MPI_ANY_TAG).
comm
is the communicator
status
is an array or structure of information that is returned. For example, if you specify a wildcard for source or tag, status will tell you the actual rank or tag for the message received.

Line 27 Exiting from MPI

The last call you should make in each process is to MPI_Finalize. This helps ensure that MPI exits cleanly, and that nothing is left over on the nodes when you are done. In order for the overall application to complete cleanly, all pending (non-blocking) communication should be completed before calling MPI_Finalize.

Note that your code can continue to execute after calling MPI_Finalize, but it can no longer call MPI routines.

int MPI_Finalize()
 
©  |   Cornell University    |   Center for Advanced Computing    |   Copyright Statement    |   Inclusivity Statement