
More information about MPI 2 is available on the WWW at:
Used by the programmer to specify the source and destination of messages. Often used conditionally by the application to control program execution (if rank=0 do this / if rank=1 do that).
A group possesses its own unique indentifier (handle) assigned by the system and unknown to the user. That is, a group is represented by an opaque object - the user does not know the internal structure and must call an inquiry routine to determine its attributes.
A group is always associated with a communicator. Initially, all processes are members of the group given by the predefined communicator MPI_COMM_WORLD.
A communicator posseses its own unique indentifier (handle) assigned by the system and unknown to the user. That is, a communicator is represented by an opaque object - the user does not know the internal structure and must call an inquiry routine to determine its attributes.
Most MPI subroutines require you to specify the communicator as an argument. MPI_COMM_WORLD is the predefined communicator which includes all processes in the MPI application.
It is not safe to modify or use the application buffer after completion of a non-blocking send. It is the programmer's responsibility to insure that the application buffer is free for reuse.
Non-blocking communications are primarily used to overlap computation with communication to effect performance gains.
MPI_Init (argc,argv)
MPI_INIT (ierror)
MPI_Finalize ()
MPI_FINALIZE (ierror)
MPI_Comm_size (comm,*size)
MPI_COMM_SIZE (comm,size,ierror)
MPI_Comm_rank (comm,*rank)
MPI_COMM_RANK (comm,rank,ierror)
MPI_Abort (comm,errorcode)
MPI_ABORT (comm,errorcode,ierror)
MPI_Get_processor_name (*name,*resultlength)
MPI_GET_PROCESSOR_NAME (name,resultlength,ierror)
MPI_Initialized (*flag)
MPI_INITIALIZED (flag,ierror)
MPI_Wtime ()
MPI_WTIME ()
MPI_Wtick ()
MPI_WTICK ()
#include "mpi.h"
#include <stdio.h>
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, rc;
rc = MPI_Init(&argc,&argv);
if (rc != 0) {
printf ("Error starting MPI program. Terminating.\n");
MPI_Abort(MPI_COMM_WORLD, rc);
}
MPI_Comm_size(MPI_COMM_WORLD,&numtasks);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
printf ("Number of tasks= %d My rank= %d\n", numtasks,rank);
/******* do some work *******/
MPI_Finalize();
}
program simple
include 'mpif.h'
integer numtasks, rank, ierr, rc
call MPI_INIT(ierr)
if (ierr .ne. 0) then
print *,'Error starting MPI program. Terminating.'
call MPI_ABORT(MPI_COMM_WORLD, rc, ierr)
end if
call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr)
print *, 'Number of tasks=',numtasks,' My rank=',rank
C ****** do some work ******
call MPI_FINALIZE(ierr)
end
MPI C data types
MPI_CHAR: signed char
MPI_SHORT: signed short int
MPI_INT: signed int
MPI_LONG: signed long int
MPI_UNSIGNED_CHAR: unsigned char
MPI_UNSIGNED_SHORT: unsigned short int
MPI_UNSIGNED: unsigned int
MPI_UNSIGNED_LONG: unsigned long int
MPI_FLOAT: float
MPI_DOUBLE: double
MPI_LONG_DOUBLE: long double
MPI_BYTE: 8 binary digits; can be
used to turn off data
format conversion
MPI_PACKED: data packed/unpacked with
MPI_Pack()/MPI_Unpack
MPI Fortran data types
MPI_CHARACTER: character(1)
MPI_INTEGER: integer
MPI_REAL: real
MPI_DOUBLE_PRECISION: double precision
MPI_COMPLEX: complex
MPI_LOGICAL: logical
MPI_BYTE: 8 binary digits; can be
used to turn off data
format conversion
MPI_PACKED: data packed/unpacked with
MPI_Pack()/MPI_Unpack
MPI_Send (*buf,count,datatype,dest,tag,comm)
MPI_SEND (buf,count,datatype,dest,tag,comm,ierror)
MPI_Recv (*buf,count,datatype,source,tag,comm,*status)
MPI_RECV (buf,count,datatype,source,tag,comm,status,ierror)
MPI_Ssend (*buf,count,datatype,dest,tag,comm,ierror)
MPI_SSEND (buf,count,datatype,dest,tag,comm,ierror)
MPI_Bsend (*buf,count,datatype,dest,tag,comm)
MPI_BSEND (buf,count,datatype,dest,tag,comm,ierror)
MPI_Buffer_attach (*buffer,size)
MPI_Buffer_detach (*buffer,size)
MPI_BUFFER_ATTACH (buffer,size,ierror)
MPI_BUFFER_DETACH (buffer,size,ierror)
MPI_Rsend (*buf,count,datatype,dest,tag,comm)
MPI_RSEND (buf,count,datatype,dest,tag,comm,ierror)
MPI_Sendrecv (*sendbuf,sendcount,sendtype,dest,sendtag,
*recvbuf,recvcount,recvtype,source,recvtag,
comm,*status)
MPI_SENDRECV (sendbuf,sendcount,sendtype,dest,sendtag,
recvbuf,recvcount,recvtype,source,recvtag,
comm,status,ierror)
MPI_Probe (source,tag,comm,*status)
MPI_PROBE (source,tag,comm,status,ierr)
Task 0 - pings task 1 and awaits return ping
#include "mpi.h"
#include <stdio.h>
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, dest, source, rc, tag=1;
char inmsg, outmsg='x';
MPI_Status Stat;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank == 0) {
dest = 1;
source = 1;
rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
rc = MPI_Recv(&inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
}
else if (rank == 1) {
dest = 0;
source = 0;
rc = MPI_Recv(&inmsg, 1, MPI_CHAR, source, tag, MPI_COMM_WORLD, &Stat);
rc = MPI_Send(&outmsg, 1, MPI_CHAR, dest, tag, MPI_COMM_WORLD);
}
MPI_Finalize();
}
MPI_Isend (*buf,count,datatype,dest,tag,comm,*request)
MPI_ISEND (buf,count,datatype,dest,tag,comm,request,ierror)
MPI_Irecv (*buf,count,datatype,source,tag,comm,*request)
MPI_IRECV (buf,count,datatype,source,tag,comm,request,ierror)
MPI_Issend (*buf,count,datatype,dest,tag,comm,*request)
MPI_ISSEND (buf,count,datatype,dest,tag,comm,request,ierror)
MPI_Ibsend (*buf,count,datatype,dest,tag,comm,*request)
MPI_IBSEND (buf,count,datatype,dest,tag,comm,request,ierror)
MPI_Irsend (*buf,count,datatype,dest,tag,comm,*request)
MPI_IRSEND (buf,count,datatype,dest,tag,comm,request,ierror)
MPI_Wait (*request,*status)
MPI_Waitany (count,*array_of_requests,*index,*status)
MPI_Waitall (count,*array_of_requests,*array_of_statuses)
MPI_Waitsome (incount,*array_of_requests,*outcount,
*array_of_offsets, *array_of_statuses)
MPI_WAIT (request,status,ierror)
MPI_WAITANY (count,array_of_requests,index,status,ierror)
MPI_WAITALL (count,array_of_requests,array_of_statuses,
ierror)
MPI_WAITSOME (incount,array_of_requests,outcount,
array_of_offsets, array_of_statuses,ierror)
MPI_Test (*request,*flag,*status)
MPI_Testany (count,*array_of_requests,*index,*flag,*status)
MPI_Testall (count,*array_of_requests,*flag,*array_of_statuses)
MPI_Testsome (incount,*array_of_requests,*outcount,
*array_of_offsets, *array_of_statuses)
MPI_TEST (request,flag,status,ierror)
MPI_TESTANY (count,array_of_requests,index,flag,status,ierror)
MPI_TESTALL (count,array_of_requests,flag,array_of_statuses,ierror)
MPI_TESTSOME (incount,array_of_requests,outcount,
array_of_offsets, array_of_statuses,ierror)
MPI_Iprobe (source,tag,comm,*flag,*status)
MPI_IPROBE (source,tag,comm,flag,status,ierr)
Nearest neighbor exchange in ring topology
#include "mpi.h"
#include <stdio.h>
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, next, prev, buf[2], tag1=1, tag2=2;
MPI_Request reqs[4];
MPI_Status stats[4];
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
prev = rank-1;
next = rank+1;
if (rank == 0) prev = numtasks - 1;
if (rank == (numtasks - 1)) next = 0;
MPI_Irecv(&buf[0], 1, MPI_INT, prev, tag1, MPI_COMM_WORLD, &reqs[0]);
MPI_Irecv(&buf[1], 1, MPI_INT, next, tag2, MPI_COMM_WORLD, &reqs[1]);
MPI_Isend(&rank, 1, MPI_INT, prev, tag2, MPI_COMM_WORLD, &reqs[2]);
MPI_Isend(&rank, 1, MPI_INT, next, tag1, MPI_COMM_WORLD, &reqs[3]);
MPI_Waitall(4, reqs, stats);
MPI_Finalize();
}
MPI_Barrier (comm)
MPI_BARRIER (comm,ierror)
MPI_Bcast (*buffer,count,datatype,root,comm)
MPI_BCAST (buffer,count,datatype,root,comm,ierror)
MPI_Scatter (*sendbuf,sendcnt,sendtype,*recvbuf,
recvcnt,recvtype,root,comm)
MPI_SCATTER (sendbuf,sendcnt,sendtype,recvbuf,
recvcnt,recvtype,root,comm,ierror)
MPI_Gather (*sendbuf,sendcnt,sendtype,*recvbuf,
recvcount,recvtype,root,comm)
MPI_GATHER (sendbuf,sendcnt,sendtype,recvbuf,
recvcount,recvtype,root,comm,ierror)
MPI_Allgather (*sendbuf,sendcount,sendtype,*recvbuf,
recvcount,recvtype,comm)
MPI_ALLGATHER (sendbuf,sendcount,sendtype,recvbuf,
recvcount,recvtype,comm,info)
MPI_Reduce (*sendbuf,*recvbuf,count,datatype,op,
root,comm)
MPI_REDUCE (sendbuf,recvbuf,count,datatype,op,
root,comm,ierror)
The predefined MPI reduction operations appear below. Users can also
define their own reduction functions.
-----------------------------------------------------------------
MPI Reduction Operation C data types FORTRAN data types
-----------------------------------------------------------------
MPI_MAX maximum integer, float integer, real, complex
MPI_MIN minimum integer, float integer, real, complex
MPI_SUM sum integer, float integer, real, complex
MPI_PROD product integer, float integer, real, complex
MPI_LAND logical and integer logical
MPI_BAND bit-wise and integer, MPI_BYTE integer, MPI_BYTE
MPI_LOR logical or integer logical
MPI_BOR bit-wise or integer, MPI_BYTE integer, MPI_BYTE
MPI_LXOR logical xor integer logical
MPI_BXOR bit-wise xor integer, MPI_BYTE integer, MPI_BYTE
MPI_MAXLOC max value combination of int combination of integer
and location float, double and real, complex,
long double double precision
MPI_MINLOC min value combination of int combination of integer
and location float, double and real, complex,
long double double precision
-----------------------------------------------------------------
MPI_Allreduce (*sendbuf,*recvbuf,count,datatype,op,comm)
MPI_ALLREDUCE (sendbuf,recvbuf,count,datatype,op,comm,ierror)
MPI_Alltoall (*sendbuf,sendcount,sendtype,*recvbuf,
recvcnt,recvtype,comm)
MPI_ALLTOALL (sendbuf,sendcount,sendtype,recvbuf,
recvcnt,recvtype,comm,ierror)
MPI_Scan (*sendbuf,*recvbuf,count,datatype,op,comm)
MPI_SCAN (sendbuf,recvbuf,count,datatype,op,comm,ierror)
Perform a scatter operation on the rows of an array
#include "mpi.h"
#include <stdio.h>
#define SIZE 4
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, sendcount, recvcount, source;
float sendbuf[SIZE][SIZE] = {
{1.0, 2.0, 3.0, 4.0},
{5.0, 6.0, 7.0, 8.0},
{9.0, 10.0, 11.0, 12.0},
{13.0, 14.0, 15.0, 16.0} };
float recvbuf[SIZE];
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
if (numtasks == SIZE) {
source = 1;
sendcount = SIZE;
recvcount = SIZE;
MPI_Scatter(sendbuf,sendcount,MPI_FLOAT,recvbuf,recvcount,
MPI_FLOAT,source,MPI_COMM_WORLD);
printf("rank= %d Results: %f %f %f %f\n",rank,recvbuf[0],
recvbuf[1],recvbuf[2],recvbuf[3]);
}
else
printf("Must specify %d processors. Terminating.\n",SIZE);
MPI_Finalize();
}
Sample program output:
rank= 0 Results: 1.000000 2.000000 3.000000 4.000000 rank= 1 Results: 5.000000 6.000000 7.000000 8.000000 rank= 2 Results: 9.000000 10.000000 11.000000 12.000000 rank= 3 Results: 13.000000 14.000000 15.000000 16.000000
MPI_Group_difference (group1,group2,*newgroup)
MPI_GROUP_DIFFERENCE (group1,group2,newgroup,ierror)
MPI_Group_excl (group,n,*ranks,*newgroup)
MPI_GROUP_EXCL (group,n,ranks,newgroup,ierror)
MPI_Group_incl (group,n,*ranks,*newgroup)
MPI_GROUP_INCL (group,n,ranks,newgroup,ierror)
MPI_Group_intersection (group1,group2,*newgroup)
MPI_GROUP_INTERSECTION (group1,group2,newgroup,ierror)
MPI_Group_union (group1,group2,*newgroup)
MPI_GROUP_UNION (group1,group2,newgroup,ierror)
MPI_Group_compare (group1,group2,*result)
MPI_GROUP_COMPARE (group1,group2,result,ierror)
MPI_Group_rank (group,*rank)
MPI_GROUP_RANK (group,rank,ierror)
MPI_Group_size (group,*size)
MPI_GROUP_SIZE (group,size,ierror)
MPI_Group_free (group)
MPI_GROUP_FREE (group,ierror)
MPI_Comm_group (comm,*group)
MPI_COMM_GROUP (comm,group,ierror)
MPI_Comm_create (comm,group,*newcomm)
MPI_COMM_CREATE (comm,group,newcomm,ierror)
MPI_Comm_dup (comm,*newcomm)
MPI_COMM_DUP (comm,newcomm,ierror)
MPI_Comm_compare (comm1,comm2,*result)
MPI_COMM_COMPARE (comm1,comm2,result,ierror)
MPI_Comm_free (*comm)
MPI_COMM_FREE (comm,ierror)
Create two different groups for separate collective communications exchange. Requires creating new communicators also.
#include "mpi.h"
#include <stdio.h>
#define NPROCS 8
#define MASTER 0
#define MSGSIZE 7
int main(argc,argv)
int argc;
char *argv[]; {
int rank, new_rank,
ranks1[4]={0,1,2,3},
ranks2[4]={4,5,6,7};
char *msg;
MPI_Group orig_group, new_group;
MPI_Comm new_comm;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
/* Extract the original group handle */
MPI_Comm_group(MPI_COMM_WORLD, &orig_group);
/* Divide tasks into two distinct groups. First */
/* create new group and then a new communicator. */
/* Find new rank in new group and setup for the */
/* collective communication broadcast if MASTER. */
if (rank < NPROCS/2) {
MPI_Group_incl(orig_group, NPROCS/2, ranks1, &new_group);
MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm);
MPI_Group_rank (new_group, &new_rank);
if (new_rank == MASTER) msg="Group 1";
}
else {
MPI_Group_incl(orig_group, NPROCS/2, ranks2, &new_group);
MPI_Comm_create(MPI_COMM_WORLD, new_group, &new_comm);
MPI_Group_rank (new_group, &new_rank);
if (new_rank == MASTER) msg="Group 2";
}
MPI_Bcast(&msg,MSGSIZE,MPI_CHAR,MASTER,new_comm);
printf("rank= %d newrank= %d msg= %s\n",rank,new_rank,msg);
MPI_Finalize();
}
Sample program output:
rank= 0 newrank= 0 msg= Group 1 rank= 1 newrank= 1 msg= Group 1 rank= 2 newrank= 2 msg= Group 1 rank= 3 newrank= 3 msg= Group 1 rank= 4 newrank= 0 msg= Group 2 rank= 5 newrank= 1 msg= Group 2 rank= 6 newrank= 2 msg= Group 2 rank= 7 newrank= 3 msg= Group 2
MPI C data types MPI Fortran data types ---------------- ---------------- MPI_CHAR MPI_CHARACTER MPI_SHORT MPI_INTEGER MPI_INT MPI_REAL MPI_LONG MPI_DOUBLE_PRECISION MPI_UNSIGNED_CHAR MPI_COMPLEX MPI_UNSIGNED_SHORT MPI_LOGICAL MPI_UNSIGNED MPI_BYTE MPI_UNSIGNED_LONG MPI_PACKED MPI_FLOAT MPI_DOUBLE MPI_LONG_DOUBLE MPI_BYTE MPI_PACKED
MPI_Type_contiguous (count,oldtype,*newtype)
MPI_TYPE_CONTIGUOUS (count,oldtype,newtype,ierr)
MPI_Type_vector (count,blocklength,stride,oldtype,*newtype)
MPI_TYPE_VECTOR (count,blocklength,stride,oldtype,newtype,ierr)
MPI_Type_indexed (count,blocklens[],offsets[],old_type,*newtype)
MPI_TYPE_INDEXED (count,blocklens(),offsets(),old_type,newtype,ierr)
MPI_Type_struct (count,blocklens[],offsets[],old_types,*newtype)
MPI_TYPE_STRUCT (count,blocklens(),offsets(),old_types,newtype,ierr)
MPI_Type_extent (datatype,*extent)
MPI_TYPE_EXTENT (datatype,extent,ierr)
Create a data type representing a row of an array and distribute a different row to all processes. Diagram here.
#include "mpi.h"
#include <stdio.h>
#define SIZE 4
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, source=0, dest, tag=1, i;
float a[SIZE][SIZE] =
{1.0, 2.0, 3.0, 4.0,
5.0, 6.0, 7.0, 8.0,
9.0, 10.0, 11.0, 12.0,
13.0, 14.0, 15.0, 16.0};
float b[SIZE];
MPI_Status stat;
MPI_Datatype rowtype;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Type_contiguous(SIZE, MPI_FLOAT, &rowtype);
MPI_Type_commit(&rowtype);
if (numtasks == SIZE) {
if (rank == 0) {
for (i=0; i<numtasks; i++)
MPI_Send(&a[i][0], 1, rowtype, i, tag, MPI_COMM_WORLD);
}
MPI_Recv(b, SIZE, MPI_FLOAT, source, tag, MPI_COMM_WORLD, &stat);
printf("rank= %d b= %3.1f %3.1f %3.1f %3.1f\n",
rank,b[0],b[1],b[2],b[3]);
}
else
printf("Must specify %d processors. Terminating.\n",SIZE);
MPI_Finalize();
}
Sample program output:
rank= 0 b= 1.0 2.0 3.0 4.0 rank= 1 b= 5.0 6.0 7.0 8.0 rank= 2 b= 9.0 10.0 11.0 12.0 rank= 3 b= 13.0 14.0 15.0 16.0
Create a data type representing a column of an array and distribute different columns to all processes. Diagram here.
#include "mpi.h"
#include <stdio.h>>
#define SIZE 4
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, source=0, dest, tag=1, i;
float a[SIZE][SIZE] =
{1.0, 2.0, 3.0, 4.0,
5.0, 6.0, 7.0, 8.0,
9.0, 10.0, 11.0, 12.0,
13.0, 14.0, 15.0, 16.0};
float b[SIZE];
MPI_Status stat;
MPI_Datatype columntype;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Type_vector(SIZE, 1, SIZE, MPI_FLOAT, &columntype);
MPI_Type_commit(&columntype);
if (numtasks == SIZE) {
if (rank == 0) {
for (i=0; i<numtasks; i++)
MPI_Send(&a[0][i], 1, columntype, i, tag, MPI_COMM_WORLD);
}
MPI_Recv(b, SIZE, MPI_FLOAT, source, tag, MPI_COMM_WORLD, &stat);
printf("rank= %d b= %3.1f %3.1f %3.1f %3.1f\n",
rank,b[0],b[1],b[2],b[3]);
}
else
printf("Must specify %d processors. Terminating.\n",SIZE);
MPI_Finalize();
}
Sample program output:
rank= 0 b= 1.0 5.0 9.0 13.0 rank= 1 b= 2.0 6.0 10.0 14.0 rank= 2 b= 3.0 7.0 11.0 15.0 rank= 3 b= 4.0 8.0 12.0 16.0
Create a datatype by extracting variable portions of an array and distribute to all tasks. Diagram here.
#include "mpi.h"
#include <stdio.h>
#define NELEMENTS 6
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, source=0, dest, tag=1, i;
int blocklengths[2], displacements[2];
float a[16] =
{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
float b[NELEMENTS];
MPI_Status stat;
MPI_Datatype indextype;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
blocklengths[0] = 4;
blocklengths[1] = 2;
displacements[0] = 5;
displacements[1] = 12;
MPI_Type_indexed(2, blocklengths, displacements, MPI_FLOAT, &indextype);
MPI_Type_commit(&indextype);
if (rank == 0) {
for (i=0; i<numtasks; i++)
MPI_Send(a, 1, indextype, i, tag, MPI_COMM_WORLD);
}
MPI_Recv(b, NELEMENTS, MPI_FLOAT, source, tag, MPI_COMM_WORLD, &stat);
printf("rank= %d b= %3.1f %3.1f %3.1f %3.1f %3.1f %3.1f\n",
rank,b[0],b[1],b[2],b[3],b[4],b[5]);
MPI_Finalize();
}
Sample program output:
rank= 0 b= 6.0 7.0 8.0 9.0 13.0 14.0 rank= 1 b= 6.0 7.0 8.0 9.0 13.0 14.0 rank= 2 b= 6.0 7.0 8.0 9.0 13.0 14.0 rank= 3 b= 6.0 7.0 8.0 9.0 13.0 14.0
Create a data type which represents a particle and distribute an array of such particles to all processes. Diagram here.
#include "mpi.h"
#include <stdio.h>
#define NELEM 25
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, source=0, dest, tag=1, i;
typedef struct {
float x, y, z;
float velocity;
int n, type;
} Particle;
Particle p[NELEM], particles[NELEM];
MPI_Datatype particletype, oldtypes[2];
int blockcounts[2];
/* MPI_Aint type used to be consistent with syntax of */
/* MPI_Type_extent routine */
MPI_Aint offsets[2], extent;
MPI_Status stat;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
/* Setup description of the 4 MPI_FLOAT fields x, y, z, velocity */
offsets[0] = 0;
oldtypes[0] = MPI_FLOAT;
blockcounts[0] = 4;
/* Setup description of the 2 MPI_INT fields n, type */
/* Need to first figure offset by getting size of MPI_FLOAT */
MPI_Type_extent(MPI_FLOAT, &extent);
offsets[1] = 4 * extent;
oldtypes[1] = MPI_INT;
blockcounts[1] = 2;
/* Now define structured type and commit it */
MPI_Type_struct(2, blockcounts, offsets, oldtypes, &particletype);
MPI_Type_commit(&particletype);
/* Initialize the particle array and then send it to each task */
if (rank == 0) {
for (i=0; i<NELEM; i++) {
particles[i].x = i * 1.0;
particles[i].y = i * -1.0;
particles[i].z = i * 1.0;
particles[i].velocity = 0.25;
particles[i].n = i;
particles[i].type = i % 2;
}
for (i=0; i<numtasks; i++)
MPI_Send(particles, NELEM, particletype, i, tag, MPI_COMM_WORLD);
}
MPI_Recv(p, NELEM, particletype, source, tag, MPI_COMM_WORLD, &stat);
/* Print a sample of what was received */
printf("rank= %d %3.2f %3.2f %3.2f %3.2f %d %d\n", rank,p[3].x,
p[3].y,p[3].z,p[3].velocity,p[3].n,p[3].type);
MPI_Finalize();
}
Sample program output:
rank= 0 3.00 -3.00 3.00 0.25 3 1 rank= 2 3.00 -3.00 3.00 0.25 3 1 rank= 1 3.00 -3.00 3.00 0.25 3 1 rank= 3 3.00 -3.00 3.00 0.25 3 1

MPI_Cart_coords (comm,rank,maxdims,*coords[])
MPI_CART_COORDS (comm,rank,maxdims,coords(),ierr)
MPI_Cart_create (comm_old,ndims,*dims[],*periods,reorder,*comm_cart)
MPI_CART_CREATE (comm_old,ndims,dims(),periods,reorder,comm_cart,ierr)
MPI_Cart_get (comm,maxdims,*dims,*periods,*coords[])
MPI_CART_GET (comm,maxdims,dims,periods,coords(),ierr)
MPI_Cart_map (comm_old,ndims,*dims[],*periods[],*newrank)
MPI_CART_MAP (comm_old,ndims,dims(),periods(),newrank,ierr)
MPI_Cart_rank (comm,*coords[],*rank)
MPI_CART_RANK (comm,coords(),rank,ierr)
MPI_Cart_shift (comm,direction,displ,*source,*dest)
MPI_CART_SHIFT (comm,direction,displ,source,dest,ierr)
MPI_Cart_sub (comm,*remain_dims[],*comm_new)
MPI_CART_SUB (comm,remain_dims(),comm_new,ierr)
MPI_Cartdim_get (comm,*ndims)
MPI_CARTDIM_GET (comm,ndims,ierr)
MPI_Dims_create (nnodes,ndims,*dims[])
MPI_DIMS_CREATE (nnodes,ndims,dims(),ierr)
MPI_Graph_create (comm_old,nnodes,*index[],*edges[],
reorder,*comm_graph)
MPI_GRAPH_CREATE (comm_old,nnodes,index(),edges(),
reorder,comm_graph,ierr)
MPI_Graph_get (comm,maxindex,maxedges,*index[],*edges[])
MPI_GRAPH_GET (comm,maxindex,maxedges,index(),edges(),ierr)
MPI_Graph_map (comm_old,nnodes,*index[],*edges[],*newrank)
MPI_GRAPH_MAP (comm_old,nnodes,index(),edges(),newrank,ierr)
MPI_Graph_neighbors (comm,rank,maxneighbors,*neighbors[])
MPI_GRAPH_NEIGHBORS (comm,rank,maxneighbors,neighbors(),ierr)
MPI_Graphdims_get (comm,*nnodes,*nedges)
MPI_GRAPHDIMS_GET (comm,nnodes,nedges,ierr)
MPI_Topo_test (comm,*top_type)
MPI_TOPO_TEST (comm,top_type,ierr)
Create a 4 x 4 Cartesian topology from 16 processors and have each process exchange its rank with four neighbors.
#include "mpi.h"
#include <stdio.h>
#define SIZE 16
#define UP 0
#define DOWN 1
#define LEFT 2
#define RIGHT 3
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, source, dest, outbuf, i, tag=1,
inbuf[4]={MPI_PROC_NULL,MPI_PROC_NULL,MPI_PROC_NULL,MPI_PROC_NULL,},
nbrs[4], dims[2]={4,4},
periods[2]={0,0}, reorder=0, coords[2];
MPI_Request reqs[8];
MPI_Status stats[8];
MPI_Comm cartcomm;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
if (numtasks == SIZE) {
MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, reorder, &cartcomm);
MPI_Comm_rank(cartcomm, &rank);
MPI_Cart_coords(cartcomm, rank, 2, coords);
MPI_Cart_shift(cartcomm, 0, 1, &nbrs[UP], &nbrs[DOWN]);
MPI_Cart_shift(cartcomm, 1, 1, &nbrs[LEFT], &nbrs[RIGHT]);
outbuf = rank;
for (i=0; i<4; i++) {
dest = nbrs[i];
source = nbrs[i];
MPI_Isend(&outbuf, 1, MPI_INT, dest, tag, MPI_COMM_WORLD, &reqs[i]);
MPI_Irecv(&inbuf[i], 1, MPI_INT, source, tag, MPI_COMM_WORLD, &reqs[i+4]);
}
MPI_Waitall(8, reqs, stats);
printf("rank= %d coords= %d %d neighbors(u,d,l,r)= %d %d %d %d\n",
rank,coords[0],coords[1],nbrs[UP],nbrs[DOWN],nbrs[LEFT],
nbrs[RIGHT]);
printf("rank= %d inbuf(u,d,l,r)= %d %d %d %d\n",
rank,inbuf[UP],inbuf[DOWN],inbuf[LEFT],inbuf[RIGHT]);
}
else
printf("Must specify %d processors. Terminating.\n",SIZE);
MPI_Finalize();
}
Sample program output (partial):
rank= 0 coords= 0 0 neighbors(u,d,l,r)= -3 4 -3 1
rank= 0 inbuf(u,d,l,r)= -3 4 -3 1
rank= 1 coords= 0 1 neighbors(u,d,l,r)= -3 5 0 2
rank= 1 inbuf(u,d,l,r)= -3 5 0 2
rank= 2 coords= 0 2 neighbors(u,d,l,r)= -3 6 1 3
rank= 2 inbuf(u,d,l,r)= -3 6 1 3
. . . . .
rank= 14 coords= 3 2 neighbors(u,d,l,r)= 10 -3 13 15
rank= 14 inbuf(u,d,l,r)= 10 -3 13 15
rank= 15 coords= 3 3 neighbors(u,d,l,r)= 11 -3 14 -3
rank= 15 inbuf(u,d,l,r)= 11 -3 14 -3
MPE_Init_log ()
MPE_INIT_LOG ()
Postprocessing performed by MPE_Finish_log includes alignment and stretching of event time stamps to compensate for processor clock differences. Synchronizations are made with respect to the time stamps of MPE_Initlog and MPE_Finish_log.
MPE_Finish_log (*filename)
MPE_FINISH_LOG (filename)
MPE_Start_log ()
MPE_START_LOG ()
MPE_Stop_log ()
MPE_STOP_LOG ()
MPE_Describe_event (event,*name)
MPE_DESCRIBE_EVENT (event,name)
MPE_Describe_state (start,end,*name,*color)
MPE_DESCRIBE_STATE (start,end,name,color)
MPE_Log_event (event,intdata,*string)
MPE_LOG_EVENT (event,intdata,*string,ierr)
Defines three event states, one each for send, receive and wait communication events. Logs event records both "before" and "after" each communication event to the logfile, "logfile".
#include "mpi.h"
#include <stdio.h>
int main(argc,argv)
int argc;
char *argv[]; {
int numtasks, rank, next, prev, buf, tag=1;
MPI_Request req;
MPI_Status stat;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
printf("rank= %d starting\n",rank);
MPE_Init_log();
if (rank == 0) {
MPE_Describe_state(1,2,"SSend","green:gray3");
MPE_Describe_state(3,4,"IRecv","blue:light_gray");
MPE_Describe_state(5,6,"Wait","yellow:gray");
}
prev = rank -1;
next = rank + 1;
if (rank == (numtasks - 1))
next = 0;
if (rank == 0)
prev = numtasks-1;
MPE_Log_event(3,prev,"recv");
MPI_Irecv(&buf,1,MPI_INT,prev,tag,MPI_COMM_WORLD,&req);
MPE_Log_event(4,prev,"recvd");
MPE_Log_event(1,next,"send");
MPI_Ssend(&rank,1,MPI_INT,next,tag,MPI_COMM_WORLD);
MPE_Log_event(2,next,"sent");
MPE_Log_event(5,rank,"waitstart");
MPI_Wait(&req, &stat);
MPE_Log_event(6,rank,"waitdone");
MPE_Finish_log ("logfile");
MPI_Finalize();
}
Sample program output:
MPE_Open_graphics (*handle,comm,display,x,y,w,h,is_collective)
MPE_OPEN_GRAPHICS (handle,comm,display,x,y,,w,h,is_collective)
MPE_Close_graphics (*handle)
MPE_CLOSE_GRAPHICS (handle,ierr)
MPE_Draw_point (handle,x,y,color)
MPE_DRAW_POINT (handle,x,y,color,ierr)
MPE_Draw_points (handle,*pointlist,npoints)
MPE_DRAW_POINTS (handle,pointlist,npoints,ierr)
MPE_Draw_line (handle,x1,y1,x2,y2,color)
MPE_DRAW_LINE (handle,x1,y1,x2,y2,color,ierr)
MPE_Line_thickness (graph,thickness)
MPE_LINE_THICKNESS (graph,thickness,ierr)
MPE_Draw_circle (graph,centerx,centery,radius,color)
MPE_DRAW_CIRCLE (graph,centerx,centery,radius,color,ierr)
MPE_Fill_circle (graph,centerx,centery,radius,color)
MPE_FILL_CIRCLE (graph,centerx,centery,radius,color,ierr)
MPE_Fill_rectangle (handle,x,y,w,h,color)
MPE_FILL_RECTANGLE (handle,x,y,w,h,color,ierr)
MPE_Add_RGB_color (graph,red,green,blue,mapping)
MPE_ADD_RGB_COLOR (graph,red,green,blue,mapping,ierr)
MPE_Make_color_array (handle,ncolors,array)
MPE_MAKE_COLOR_ARRAY (handle,ncolors,array,ierr)
MPE_Num_colors (handle,*nc)
MPE_NUM_COLORS (handle,nc,ierr)
MPE_Update (handle)
MPE_UPDATE (handle,ierr)
MPE_Get_mouse_press (graph,*x,*y,*button)
MPE_GET_MOUSE_PRESS (graph,x,y,button,ierr)
##### C shell setenv MP_PROCS 4 setenv MP_HOSTFILE "NULL" setenv MP_EUILIB us setenv MP_EUIDEVICE css0 setenv MP_RMPOOL 0 setenv MP_RESD YES setenv LANG En_US setenv MP_LABELIO yes setenv MP_INFOLEVEL 1 setenv MP_PGMMODEL spmd ##### Korn Shell: export MP_PROCS=4 export MP_HOSTFILE="NULL" export MP_EUILIB=us export MP_EUIDEVICE=css0 export MP_RMPOOL=0 export MP_RESD=YES export LANG=En_US export MP_LABELIO=yes export MP_INFOLEVEL=1 export MP_PGMMODEL=spmd
/usr/nfs/bin/mpicc C Language
/usr/nfs/bin/mpixlf Fortran
/usr/nfs/packages/msg_pass/mpich/lib/rs6000/ch_eui libraries
/usr/nfs/packages/msg_pass/mpich/include include files
poe myjob
© Copyright 1995 Maui High Performance Computing Center. All rights reserved.
Documents located on the Maui High Performance Computing Center's WWW server are copyrighted by the MHPCC. Educational institutions are encouraged to reproduce and distribute these materials for educational use as long as credit and notification are provided. Please retain this copyright notice and include this statement with any copies that you make. Also, the MHPCC requests that you send notification of their use to help@@mail.mhpcc.edu.
Commercial use of these materials is prohibited without prior written permission.
18 December 1996 blaise@@mhpcc.edu