Title: COMP309/509 - Lecture 23 class: middle, center, inverse
MPI_Bcast used to distribute a value.MPI_Reduce used to accumulate (via an MPI_OP) a result at the root.MPI_Scatter used to distribute blocks of data to the nodes.MPI_Gather accumulates blocks of data in a buffer at the root.MPI_AllreduceMPI_Allgather
int MPI_Allreduce(void *sndbuf,
void *rcvbuf,
int count,
MPI_Datatype datatyp,
MPI_Op op,
MPI_Comm comm
);
sndbuf is the send bufferrcvbuf address of receive buffer significant at all nodesdatatyp is data type of elements of send bufferop is the reduce operation.comm is the communicatorint MPI_Allgather(void *sndbuf,
int sndcnt,
MPI_Datatype sndtyp,
void *rcvbuf,
int rcvcnt,
MPI_Datatype rcvtyp,
MPI_Comm comm
);
sndbuf is the address of send buffer.sndcnt is the number of elements in send buffer.sndtyp is the type of send buffer items.rcvbuf is the address of receive buffer.
rcvcnt is the number of elements for any single receive
comm is the communicator of the processes participating in the gathering.MPI_Comm_get_attr.MPI_IO attribute.MPI_PROC_NULL if no clone can do input.MPI_ANY_SOURCE if all clones can do input.
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include "mpi.h"
#define VERBOSE 0
int get_io_clone(){
int *iop, iorank, flag;
MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_IO, &iop, &flag);
if(!flag){
if(VERBOSE)fprintf(stderr, "MPI_Attr_get failed, exiting\n");
return -1;
}
if(*iop == MPI_PROC_NULL){
if(VERBOSE)fprintf(stderr, "No one can do IO!\n");
return -1;
}
if(*iop == MPI_ANY_SOURCE){
if(VERBOSE)fprintf(stderr, "Anyone can do IO!\n");
return 0;
}
MPI_Allreduce(iop, &iorank, 1, MPI_INT, MPI_MIN, MPI_COMM_WORLD);
return iorank;
}
float a; //start of interval
float b; //end of interval
int n; //number of trapezoids
typedef struct {
float a;
float b;
int n;
} ParTrapData;
printf("Enter a, b, and n\n");
scanf("%f %f %d", a_ptr, b_ptr, n_ptr);
ParTrapData ptd = { *a_ptr, *b_ptr, *n_ptr };
MPI_Bcast(&ptd, 1, ParTrapData, 0, MPI_COMM_WORLD);
ParTrapData is not the correct type!MPI_Datatype.MPI is a library of precompiled functions.MPI_Type_structMPI_Address andMPI_Type_commit#include "mpi.h"
int MPI_Type_struct(int count,
int blocklens[],
MPI_Aint indices[],
MPI_Datatype old_types[],
MPI_Datatype *newtype )
MPI_Datatype placed in newtypestruct making up the datatype.count is also the length of the next three arrays.blocklens is the number of elements in each block (element of the struct).indices is the byte displacement of each block.old_types is the type of elements in each block.MPI_Datatype mpi_ptdatatype;
int count = 3;
MPI_Aint blocks[count] = {1, 1, 1};
MPI_Aint indices[count];
MPI_Datatype old_types[count] = {MPI_Float, MPI_Float, MPI_Int};
printf("Enter a, b, and n\n");
scanf("%f %f %d", a_ptr, b_ptr, n_ptr);
ParTrapData ptd = { *a_ptr, *b_ptr, *n_ptr };
MPI_Aint addresses[count + 1];
MPI_Address(&ptd, &addresses[0]);
MPI_Address(&(ptd.a) , &addresses[1]);
MPI_Address(&(ptd.b) , &addresses[2]);
MPI_Address(&(ptd.n) , &addresses[3]);
indices[0] = addresses[1] - addresses[0];
indices[1] = addresses[2] - addresses[0];
indices[2] = addresses[3] - addresses[0];
MPI_Type_struct(count, blocks, indices, old_types, &mpi_ptdatatype);
MPI_Type_commit(&mpi_ptdatatype);#include "mpi.h"
int MPI_Type_commit(MPI_Datatype *datatype);
*datatype is the datatype to be commited#define BUFF 100
char buff[BUFF]
int position = 0;
MPI_Pack(a_ptr, 1, MPI_FLOAT, buff, BUFF, &position, MPI_COMM_WORLD);
MPI_Pack(b_ptr, 1, MPI_FLOAT, buff, BUFF, &position, MPI_COMM_WORLD);
MPI_Pack(n_ptr, 1, MPI_INT, buff, BUFF, &position, MPI_COMM_WORLD);
MPI_Bcast(buffer, BUFF, MPI_PACKED, root, MPI_COMM_WORLD);
MPI_Unpack(buff, BUFF, &position, a_ptr, 1, MPI_FLOAT, MPI_COMM_WORLD);
MPI_Unpack(buff, BUFF, &position, b_ptr, 1, MPI_FLOAT, MPI_COMM_WORLD);
MPI_Unpack(buff, BUFF, &position,n_ptr, 1, MPI_INT, MPI_COMM_WORLD);
Review:
class: middle, center, inverse