Message-Passing Interface/MPI function reference
This page lists brief explanations for the functions used in MPI.
int MPI_Send( void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm )
This sends the contents of buf
to the destination of rank dest
while the receiving end calls MPI_Recv
.
int MPI_Recv( void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status )
This fills the buf
with data comming from to the source of rank source
while the sender calls MPI_Send
.
int MPI_Bcast ( void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm )
This sends the contents of buffer
on root
to all other processes. So afterwards the first count
elements of buffer
is the same across all nodes. [1]
MPI 2.0 Connection commands
editint MPI_Open_port(MPI_Info info, char *port_name)
This creates a port to which other processes can connect. The buffer passed as port_name
string must be at least MPI_MAX_PORT_NAME
long and will contain a unique identifier which other processes will need to know in order to connect.
int MPI_Comm_accept(char *port_name, MPI_Info info, int root, MPI_Comm comm, MPI_Comm *newcomm)
After calling MPI_Open_port()
, this function waits for a connection.
int MPI_Comm_connect(char *port_name, MPI_Info info, int root, MPI_Comm comm, MPI_Comm *newcomm)
This opens a connection to another process which is waiting on MPI_Comm_accept()
. The port_name
argument must be the same as the result of the other process's port_name
returned from MPI_Open_port
.
Reduction
editThe following functions reduce arrays of data across processors to scalars on one or many processors by applying simple functions such as summation.
int MPI_Scan ( void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm )
See [4].
int MPI_Allreduce ( void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, MPI_Comm comm )
This performs an operation specified by MPI_Op
on all nodes to each node's sendbuf
. For example, if node 0 had {0, 1, 2}
and node 1 had {3, 4, 5}
in its sendbuf
, respectively, and if both called MPI_Allreduce(sendbuf, foo, 3, MPI_INT, MPI_SUM, world)
, the contents of the buffer pointed to by foo
on both would be
- {0+3, 1+4, 2+5} = {3, 5, 7}
Performance for P processes: .[5]
int MPI_Comm_split(MPI_Comm comm, int color, int key, MPI_Comm *newcomm);
MPI_Comm_split()
creates a new communicator in each process. The resulting communicators are common to the processes that provided the same color
argument. Processes can opt not to get a communicator by providing MPI_UNDEFINED
as the color
, which will produce MPI_COMM_NULL
for that process.
For example, the following code splits MPI_COMM_WORLD
into three communicators "colored" 0, 1, and 2.
#include<iostream> #include<mpi.h> using namespace std; int main(int argc, char** argv) { MPI_Init(&argc, &argv); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm comm; MPI_Comm_split(MPI_COMM_WORLD, rank % 3, -rank*2, &comm); // The keys need not be positive or contiguous. int rank2; MPI_Comm_rank(comm, &rank2); cout << "My rank was " << rank << " now " << rank2 << " color: " << rank % 3 << "\n"; MPI_Finalize(); }
Run with eight processes, this output the following (in undefined order):
My rank was 0 now 2 color: 0 My rank was 8 now 2 color: 1 My rank was 8 now 1 color: 2 My rank was 3 now 1 color: 0 My rank was 4 now 1 color: 1 My rank was 5 now 0 color: 2 My rank was 6 now 0 color: 0 My rank was 7 now 0 color: 1 My rank was 8 now 0 color: 1
Nonblocking asynchronous communication
editThe following functions work together to allow nonblocking asynchronous communications among processes.[6] One process sends while another receives. The sender must must check that the operation is complete before erasing the buffer. MPI_Wait()
is a blocking wait whereas MPI_Test
is nonblocking.
MPI_Isend()
and MPI_Irecv()
calls need not be in order. That is, process 42 could call MPI_Irecv()
three times to begin receiving from processes 37, 38, and 39 which can send at their leisure.
int MPI_Isend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request);
---
int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Request recvtag, MPI_Comm comm, MPI_Status *status);
int MPI_Wait(MPI_Request *request, MPI_Status *status);
int MPI_Test(MPI_Request *request, int* flag, MPI_Status* status);
Example code:
#include<iostream> #include<mpi.h> using namespace std; int main(int argc, char** argv) { MPI_Init(&argc, &argv); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm comm; int sources[] = {3,4,5}; int dest = 1; int tag =42; if (rank == sources[0] || rank == sources[1] || rank == sources[2]) { double x[] = { 1*rank, 2*rank, 3*rank}; MPI_Request r; MPI_Isend(x, 3, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD, &r); cout << "Process " << rank << " waiting...\n"; MPI_Status status; MPI_Wait(&r, &status); cout << "Process " << rank << " sent\n"; } else if(rank == dest) { double x[3][3]; MPI_Request r[3]; for (int i = 0; i !=3; ++i) { MPI_Irecv(x[i], 3, MPI_DOUBLE, sources[i], tag, MPI_COMM_WORLD, &r[i]); cout << "Process " << rank << " waiting for " << sources[i] << " on recv.\ \n"; } for (int i = 0; i !=3; ++i) { MPI_Status status; MPI_Wait(&r[i], &status); cout << "Process " << rank << " got " << x[i][0] << " " << x[i][1] << " " <\ < x[i][2] << ".\n"; } } MPI_Finalize(); }
[Other functions]
edit A reader requests expansion of this page to include more material. You can help by adding new material (learn how) or ask for assistance in the reading room. |
int MPI_Init(int *argc, char ***argv); int MPI_Finalize(void); int MPI_Comm_rank(MPI_Comm comm, int *rank); int MPI_Comm_size(MPI_Comm comm, int *size); int MPI_Get_count(MPI_Status *status, MPI_Datatype datatype, int *count); int MPI_Type_extent(MPI_Datatype datatype, MPI_Aint *extent); int MPI_Type_struct(int count, int *array_of_blocklengths, MPI_Aint *array_of_displacements, MPI_Datatype *array_of_types, MPI_Datatype *newtype); int MPI_Scatter(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvcount, int root, MPI_Comm comm); Performance potential: As good as log_2 (N) as bad as N. http://www.pdc.kth.se/training/Talks/MPI/Collective.I/less.html#perf_scatter_image int MPI_Gather(void* sendbuf, int sendcount, MPI_Datatype sendype, void* recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm); -- [7]
- request);
int MPI_Sendrecv(void* sendbuf, int sendcount, MPI_Datatype datatype, int dest, int sendtag, void* recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status); int MPI_Sendrecv_replace(void* buf, int count, MPI_Datatype datatype, int dest, int sendtag, int source, int int MPI_Request_free(MPI_Request *request); int MPI_Group_rank(MPI_Group group, int *rank); int MPI_Group_size(MPI_Group group, int *size); int MPI_Comm_group(MPI_Comm comm, MPI_Group *group); int MPI_Group_free(MPI_Group *group); int MPI_Group_incl(MPI_Group *group, int n, int *ranks, MPI_Group *newgroup); int MPI_Comm_create(MPI_Comm comm, MPI_Group group, MPI_Comm *newgroup); int MPI_Wtime(void); int MPI_Get_processor_name(char *name, int *resultlen);
External links
edit- An excellent explanation of MPI semantics
- “Collective Communication” by Dr. Dave Ennis
This page or section is an undeveloped draft or outline. You can help to develop the work, or you can ask for assistance in the project room. |