MPI

Distributed-memory parallelism across processes/nodes using the Message Passing Interface.

Distributed-memory parallelism across processes/nodes using the Message Passing Interface.

29.1 Hello MPI

program hello_mpi
  use mpi_f08                      ! modern Fortran binding (type-safe)
  implicit none
  integer :: rank, nprocs
  call MPI_Init()
  call MPI_Comm_rank(MPI_COMM_WORLD, rank)
  call MPI_Comm_size(MPI_COMM_WORLD, nprocs)
  print '(a, i0, a, i0)', "Hello from rank ", rank, " of ", nprocs
  call MPI_Finalize()
end program hello_mpi
mpifort hello_mpi.f90 -o hello_mpi      # Open MPI / MPICH / Intel MPI wrapper
mpirun -np 4 ./hello_mpi

29.2 Point-to-point & collectives

real(8) :: local_sum, global_sum, buf(100)
type(MPI_Status) :: status
type(MPI_Request) :: req

! Send / receive
if (rank == 0) then
  call MPI_Send(buf, 100, MPI_DOUBLE_PRECISION, 1, 0, MPI_COMM_WORLD)
else if (rank == 1) then
  call MPI_Recv(buf, 100, MPI_DOUBLE_PRECISION, 0, 0, MPI_COMM_WORLD, status)
end if

! Non-blocking
call MPI_Isend(buf, 100, MPI_DOUBLE_PRECISION, dest, tag, MPI_COMM_WORLD, req)
call MPI_Wait(req, status)

! Collectives
call MPI_Bcast(params, 10, MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD)
call MPI_Reduce(local_sum, global_sum, 1, MPI_DOUBLE_PRECISION, MPI_SUM, 0, MPI_COMM_WORLD)
call MPI_Allreduce(local_sum, global_sum, 1, MPI_DOUBLE_PRECISION, MPI_SUM, MPI_COMM_WORLD)
call MPI_Scatter(full, nloc, MPI_DOUBLE_PRECISION, part, nloc, MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD)
call MPI_Gather(part, nloc, MPI_DOUBLE_PRECISION, full, nloc, MPI_DOUBLE_PRECISION, 0, MPI_COMM_WORLD)
call MPI_Barrier(MPI_COMM_WORLD)
t = MPI_Wtime()

29.3 Parallel π example

program mpi_pi
  use mpi_f08
  implicit none
  integer, parameter :: n = 100000000
  integer :: rank, nprocs, i
  real(8) :: h, x, local, pi
  call MPI_Init()
  call MPI_Comm_rank(MPI_COMM_WORLD, rank)
  call MPI_Comm_size(MPI_COMM_WORLD, nprocs)
  h = 1.0d0 / n
  local = 0.0d0
  do i = rank + 1, n, nprocs               ! cyclic distribution of work
    x = h * (i - 0.5d0)
    local = local + 4.0d0 / (1.0d0 + x * x)
  end do
  local = local * h
  call MPI_Reduce(local, pi, 1, MPI_DOUBLE_PRECISION, MPI_SUM, 0, MPI_COMM_WORLD)
  if (rank == 0) print '(a, f18.15)', "pi = ", pi
  call MPI_Finalize()
end program mpi_pi

29.4 Advanced MPI topics

Domain decomposition & halo exchange (MPI_Sendrecv), Cartesian topologies (MPI_Cart_create, MPI_Cart_shift), derived datatypes (MPI_Type_vector for strided columns), one-sided communication (RMA), parallel I/O (MPI-IO, parallel HDF5/NetCDF), hybrid MPI+OpenMP, communicators/groups, profiling tools (Score-P, TAU, Intel Trace Analyzer).