SPMD, communicators, point-to-point and collectives
After this lecture, you can
The same program runs on every process; each operates on a subset of the data.
Figure 1: One executable, launched as many ranks: each rank has its own private memory and operates on different data; ranks communicate only via the network.
Open-source implementations
Tools you’ll use
mpicc, mpic++, mpif90, …mpiexec, mpirun, …Figure 2: A message is a payload (count × datatype) plus an envelope: destination/source rank, tag and communicator. A receive matches a send only when all envelope fields agree.
Send/Recv/Sendrecv) – the envelope decides which receive matches which sendBcast/Reduce/Scatter/Gather) – next slidesAll processes in an MPI program share the communicator MPI_COMM_WORLD.
#include <mpi.h>
#include <stdio.h>
int main(int argc, char** argv) {
MPI_Init(&argc, &argv);
int world_size, world_rank;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
printf("Hello from process %d of %d\n", world_rank, world_size);
MPI_Finalize();
return 0;
}
Figure 3: Bcast distributes one value to all; Scatter deals out pieces; Gather collects them; Allreduce combines values and gives everyone the result.
These four cover 90% of what you need; the full list is in the references (see Reading).
For a Send/Recv pair to succeed:
MPI_ANY_SOURCE)MPI_ANY_TAG)MPI_Send/MPI_Recv – simple but easy to deadlockMPI_Isend/MPI_Irecv + MPI_Waitall – overlap communication with computationMPI_Sendrecv – send and receive in one call, avoids deadlock by construction
Figure 4: Two ranks that both MPI_Send first wait for each other forever. MPI_Sendrecv schedules the send and receive halves internally so matching pairs can never block each other.
The standard deadlock-free tool for halo exchange (next lecture). MPI_PROC_NULL as partner turns either half into a no-op.
| Operation | Function | Use case |
|---|---|---|
| Broadcast | MPI_Bcast |
one process → all |
| Reduction | MPI_Reduce / MPI_Allreduce |
sum / max / min |
| Gather | MPI_Gather / MPI_Allgather |
collect from all |
| Scatter | MPI_Scatter |
distribute to all |
Figure 5: Throw \(N\) random points into the unit square; count \(s_i = 1\) if \(x_i^2 + y_i^2 < 1\). Then \(\pi \approx 4 \sum s_i / N\).
Trivially parallel: each rank generates a fraction of the points and counts hits; one reduction combines the results.
\[\pi \approx \frac{4}{N} \sum_{i=1}^{N} \Theta\big(1 - (x_i^2 + y_i^2)\big)\]
Almost every parallel program decomposes this way; the reduction is the part that costs.
A reduction over \(s\) ranks combines \(d_0 \star d_1 \star \dots \star d_{s-1}\):
MPI_Reduce does internallyFor \(s = 1024\): 1023 steps vs. 10 steps.
Caveat: the tree changes the order of additions – and floating-point addition is not associative → results may differ bit-wise between runs and rank counts.
A reduction performs \(d_0 \star d_1 \star \dots \star d_{s-1}\).
For floats, the order of summation matters because addition is not strictly associative:
\[\big[(d_0 + d_1) + (d_2 + d_3)\big] + \dots \;\neq\; \big((((d_0 + d_1) + d_2) + d_3) + \dots\big)\]
⇒ Different process counts may give bit-different results, even if mathematically the sum is the same.
Figure 6: Without GPU-aware MPI, every message is staged through host memory on both sides. GPU-aware MPI sends directly from device memory (GPUDirect RDMA).
This works because of the Unified Virtual Address Space (UVA): host and device pointers live in the same numerical address range, so MPI can tell from a pointer where the data resides (UVA is not Unified Memory). 3–50× faster for large messages; requires a CUDA-/HIP-aware MPI build (e.g. mpi/openmpi/5.0-nvidia on bwUniCluster).
Kokkos::fence() before passing device pointers to MPI – GPU kernels are asynchronous and may still be runningSend/Recv/Sendrecv) and collectives (Bcast, Scatter, Gather, Allreduce) cover almost everythingMPI_Sendrecv avoids the classic send/send deadlock by constructionKokkos::fence() before every MPI call on device data, use GPU-aware MPI when availableHPC: Parallelization on GPUs and Accelerators