start job on n processors do i=1 to j each processor does some calculation pass messages between processor end do end job
#include
/* Initialize MPI */
MPI_Init(&argc, &argv);
/* How many total PEs are there */
MPI_Comm_size(MPI_COMM_WORLD, &nPEs);
/* What node am I (what is my rank? */
MPI_Comm_rank(MPI_COMM_WORLD, &iam);
...
MPI_Finalize();
include 'mpif.h'
c Initialize MPI
call MPI_Init(ierr)
c Find total number of PEs
call MPI_Comm_size(MPI_COMM_WORLD, nPEs, ierr)
c Find the rank of this node
call MPI_Comm_rank(MPI_COMM_WORLD, iam, ierr)
...
call MPI_Finalize(ierr)
MPI_Send(&buffer, count,
datatype,
destination, tag,
communicator);
call MPI_Send(buffer, count,
datatype,
destination, tag,
communicator, ierr)
MPI_Recv(&buffer, COUNT,
datatype,
source, tag,
communicator,&status);
call MPI_Recv(buffer, COUNT,
datatype,
source, tag,
communicator, status, ierr)
C MPI Types |
||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Fortran MPI Types |
||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
MPI_Status status;
int buffer[5];
int error;
error = MPI_Recv(&buffer, 5, MPI_INTEGER,
MPI_ANY_SOURCE,
MPI_ANY_TAG,
MPI_COMM_WORLD,&status);
MPI_Status status;
INTEGER STATUS(MPI_STATUS_SIZE)
MPI_Bcast(&buffer, COUNT,
datatype,
root, communicator);
call MPI_Bcast(buffer, COUNT,
datatype,
root,
communicator, ierr)
int MPI_Reduce(&sendbuf, &recvbuf, count,
datatype, operation,root,
communicator)
call MPI_Reduce(sendbuf, recvbuf,
count, datatype, operation,root
communicator, ierr)
MPI_MAX Maximum MPI_MIN Minimum MPI_PROD Product MPI_SUM Sum MPI_LAND Logical and MPI_LOR Logical or MPI_LXOR Logical exclusive or MPI_BAND Bitwise and MPI_BOR Bitwise or MPI_BXOR Bitwise exclusive or MPI_MAXLOC Maximum value and location MPI_MINLOC Minimum value and location
double sum_partial, sum_global;
sum_partial = ...;
ierr = MPI_Allreduce( &sum_partial, &sum_global,
1, MPI_DOUBLE_PRECISION,
MPI_SUM,
MPI_COMM_WORLD);
double precision sum_partial, sum_global
sum_partial = ...
call MPI_Allreduce(sum_partial, sum_global,
1, MPI_DOUBLE_PRECISION,
MPI_SUM,
MPI_COMM_WORLD, ierr)
x(0) |
x(1) |
x(2) |
|
|---|---|---|---|
NODE 0 |
A0 |
B0 |
C0 |
NODE 1 |
A1 |
B1 |
C1 |
NODE 2 |
A2 |
B2 |
C2 |
x(0) |
x(1) |
x(2) |
|
|---|---|---|---|
NODE 0 |
A0+A1+A2 |
B0+B1+B2 |
C0+C1+C2 |
NODE 1 |
A0+A1+A2 |
B0+B1+B2 |
C0+C1+C2 |
NODE 2 |
A0+A1+A2 |
B0+B1+B2 |
C0+C1+C2 |
x(0) |
x(1) |
x(2) |
|
|---|---|---|---|
NODE 0 |
A0 |
B0 |
C0 |
NODE 1 |
A1 |
B1 |
C1 |
NODE 2 |
A2 |
B2 |
C2 |
x(0) |
x(1) |
x(2) |
|
|---|---|---|---|
NODE 0 |
A0+A1+A2 |
B0+B1+B2 |
C0+C1+C2 |
NODE 1 |
... |
... |
... |
NODE 2 |
... |
... |
... |
int MPI_Barrier(MPI_Comm comm )
INTEGER COMM, IERROR
MPI_BARRIER(COMM, IERROR)
int MPI_Isend(void* buf, int count,
MPI_Datatype datatype, int dest,
int tag, MPI_Comm comm,
MPI_Request *request)
MPI_ISEND(BUF, COUNT, DATATYPE,
DEST, TAG, COMM, REQUEST,IERROR)
int MPI_Irecv(void* buf, int count,
MPI_Datatype datatype, int source,
int tag, MPI_Comm comm, MPI_Request *request)
MPI_IRECV(BUF, COUNT, DATATYPE, SOURCE, TAG,
COMM, REQUEST,IERROR)
int MPI_Wait(MPI_Request *request,
MPI_Status *status)
INTEGER REQUEST, STATUS(MPI_STATUS_SIZE), IERROR
MPI_WAIT(REQUEST, STATUS, IERROR)
int MPI_Test(MPI_Request *request,
int *flag, MPI_Status *status)
LOGICAL FLAG
INTEGER REQUEST, STATUS(MPI_STATUS_SIZE), IERROR
MPI_TEST(REQUEST, FLAG, STATUS, IERROR)
call MPI_Isend (buffer,count,datatype,dest,tag,
comm, request, ierr)
Do other work
10 call MPI_Test (request, flag, status, ierr)
if (.not. flag) goto 10
int MPI_Probe(int source, int tag, MPI_Comm comm,
MPI_Status *status)
INTEGER SOURCE,TAG,COMM,STATUS(MPI_STATUS_SIZE),IERROR
MPI_PROBE(SOURCE, TAG, COMM, STATUS, IERROR)
! How to use probe and get_count to find the size of a message program probe_it include 'mpif.h' integer myid,numprocs integer status(MPI_STATUS_SIZE) integer mytag,i,icount,ierr call MPI_INIT( ierr ) call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr ) call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr ) mytag=123 i=0 icount=0 if(myid .eq. 0)then i=100 icount=1 call MPI_SEND(i,icount,MPI_INTEGER,1,mytag,MPI_COMM_WORLD,ierr) endif if(myid .eq. 1)then call mpi_probe(0,mytag,MPI_COM_WORLD,status,ierr) call mpi_get_count(status,MPI_INTEGER,icount,ierr) write(*,*)"getting ", icount call mpi_recv & (i,icount,MPI_INTEGER,0,mytag,MPI_COMM_WORLD,status,ierr) write(*,*)"i=",i endif call mpi_finalize(ierr) stop end
int MPI_Comm_create(MPI_Comm comm, MPI_Group group,
MPI_Comm*newcomm)
MPI_COMM_CREATE(COMM, GROUP, NEWCOMM, IERROR)
INTEGER COMM, GROUP, NEWCOMM, IERROR
int MPI_Comm_group(MPI_Comm comm, MPI_Group *group)
MPI_COMM_GROUP(COMM, GROUP, IERROR)
INTEGER COMM, GROUP, IERROR
int MPI_Group_incl(MPI_Group group, int n,
int *ranks,MPI_Group *newgroup)
MPI_GROUP_INCL(GROUP, N, RANKS, NEWGROUP, IERROR)
INTEGER GROUP, N, RANKS(*), NEWGROUP, IERROR
int MPI_Group_excl(MPI_Group group, int n,
int *ranks,MPI_Group *newgroup)
MPI_GROUP_EXCL(GROUP, N, RANKS, NEWGROUP, IERROR)
INTEGER GROUP, N, RANKS(*), NEWGROUP, IERROR
int MPI_TYPE_STRUCT(int count,
int *array_of_blocklengths,
MPIAint *array_of_displacement,
MPI_Datatype *array_of_types,
MPI_Datatype *newtype);
int MPI_TYPE_COMMIT(MPI_Datatype *datatype);
MPI_TYPE_STRUCT(count,
array_of_blocklengths,
array_of_displacement,
array_of_types,
newtype,ierror)
MPI_TYPE_COMMIT(newtype, ierror)
! t contains the types that make up the structure
t(1)=MPI_DOUBLE_PRECISION
t(2)=MPI_INTEGER
t(3)=MPI_LOGICAL
! b contains the number of each type
b(1)=3;b(2)=10;b(3)=2
! d contains the byte offset of
! the start of each type
d(1)=0;d(2)=24;d(3)=64
call MPI_TYPE_STRUCT(3,b,d,t,MPI_CHARLES,mpi_err)
call MPI_TYPE_COMMIT(MPI_CHARLES,mpi_err)
int MPI_Gatherv (void *sendbuf, int *sendcnts,
MPI_Datatype sendtype,
void *recvbuf, int *recvcnts,
int *rdispls,
MPI_Datatype recvtype,
MPI_Comm comm );
MPI_Gatherv (sendbuf,sendcnts,sendtype,
recvbuf, recvcnts,rdispls,recvtype,
comm,ierror);
int MPI_Scatterv (void *sendbuf, int *sendcnts,
MPI_Datatype sendtype,
void *recvbuf, int *recvcnts,
MPI_Datatype recvtype,
MPI_Comm comm );
MPI_Scatterv (sendbuf,sendcnts,sendtype,
recvbuf, recvcnts,recvtype,
comm,ierror);
int MPI_Alltoallv (void *sendbuf, int *sendcnts,
int *sdispls,
MPI_Datatype sendtype,
void *recvbuf, int *recvcnts,
int *rdispls,
MPI_Datatype recvtype,
MPI_Comm comm );
MPI_Alltoallv (sendbuf,sendcnts,sdispls,sendtype,
recvbuf, recvcnts,rdispls,recvtype,
comm,ierror);
Start with a sorted list on each node active =1 while (2*active < N) active = 2 * active if(myid >= active)then send(data , myid-active) return endif if(myid + active < N)then recv(new_data, myid+active) data = merge(data , new_data) endif while(active > 1) active = active / 2 if(myid >= active)then send(data, myid-active) else recv(new_data , myid+active) data = merge(data, new_data) endif endwhile
| node | stage 1a | stage 1b | stage 2a | stage 2b | stage 3a | stage 3b |
| 0 | 0<-4 | merge | 0<-2 | merge | 0<-1 | merge |
| 1 | 1<-5 | merge | 1<-3 | merge | 1->0 | - |
| 2 | 2<-6 | merge | 2->0 | - |
- |
- |
| 3 | 3<-7 | merge | 3->1 | - |
- |
- |
| 4 | 4->0 | - |
- |
- |
- |
- |
| 5 | 5->1 | - |
- |
- |
- |
- |
| 6 | 6->2 | - |
- |
- |
- |
- |
| 7 | 7->3 | - |
- |
- |
- |
- |
!find n2, the power of two >= numnodes do i=1,n2-1 !do xor to find the processor xchng xchng=xor(i,myid) if(xchng <= (numnodes-1))then if(myid < xchng)then send from myid to xchng recv from xchng to myid else recv from xchng to myid send from myid to xchng endif else skip this stage endif enddo
Stage |
node 0 |
node 1 |
node 2 |
node 3 |
node 4 |
| 1a | 0 to 1 | 0 to 1 | 2 to 3 | 2 to 3 | skip |
| 1b | 1 to 0 | 1 to 0 | 3 to 2 | 3 to 2 | skip |
| 2a | 0 to 2 | 1 to 3 | 0 to 2 | 1 to 3 | skip |
| 2b | 2 to 0 | 3 to 1 | 2 to 0 | 3 to 1 | skip |
| 3a | 0 to 3 | 1 to 2 | 1 to 2 | 0 to 3 | skip |
| 3b | 3 to 4 | 2 to 1 | 2 to 1 | 3 to 0 | skip |
| 4a | 0 to 4 | skip | skip | skip | 0 to 4 |
| 4b | 4 to 0 | skip | skip | skip | 4 to 0 |
| 5a | skip | 1 to 4 | skip | skip | 1 to 4 |
| 5b | skip | 4 to 1 | skip | skip | 4 to 1 |
| 6a | skip | skip | 2 to 4 | skip | 2 to 4 |
| 6b | skip | skip | 4 to 2 | skip | 4 to 2 |
| 7a | skip | skip | skip | 3 to 4 | 2 to 4 |
| 7b | skip | skip | skip | 4 to 3 | 4 to 3 |
mpxlf program.f mpxlf90 program.f mpcc program.c poe a.out -procs 3 -rmpool 1
f90 program.f cc program.c mpprun -n 3 a.out