In a single-process C program, functions communicate through shared memory: one writes to a variable and another reads it. Across processes with separate address spaces — especially on different machines — that doesn't work. The low-level solution is sockets: send(fd, buf, n, 0) pushes bytes out and recv(fd, buf, n, 0) pulls them in on the other end. MPI point-to-point communication is the same idea at a higher level: you address messages by process rank instead of file descriptor, and the runtime handles the network transport. MPI_Send transmits a buffer to a target rank; MPI_Recv receives into a buffer from a source rank. Both specify the buffer address, element count, datatype, peer rank, message tag, and communicator. The tag is an integer that distinguishes between multiple messages from the same sender.
if (rank == 0) { int x = 42; MPI_Send(&x, 1, MPI_INT, 1, 0, MPI_COMM_WORLD); } else if (rank == 1) { int x; MPI_Recv(&x, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); printf("received %d\n", x); }
MPI_ANY_SOURCE and MPI_ANY_TAG are wildcards that match any sender or tag in MPI_Recv. When wildcards are used, the actual source, tag, and element count are returned in the MPI_Status struct. MPI_Sendrecv combines a send and a receive in a single call, which is the simplest way to avoid deadlock in patterns where every process must both send and receive simultaneously.