MPI skill for distributed-memory parallel programming. Use when writing MPI_Send/Recv programs, collective operations, non-blocking communication, MPI+OpenMP hybrid, or debugging with mpirun. Activates on queries about MPI_Init, MPI_Allreduce, MPI_Isend, mpirun, MPI-IO, or MPI performance.

GitHub
Install command
npx skhub add mohitmishra786/mpi
Markdown
SKILL.md

MPI

Purpose

Guide agents through MPI (Message Passing Interface) programming: point-to-point and collective communication, non-blocking operations, subcommunicators, MPI+OpenMP hybrid patterns, process launching with mpirun, debugging techniques, MPI-IO, and common performance issues.

When to Use

  • Parallelizing across multiple nodes or sockets
  • Implementing distributed algorithms (matrix decompose, FFT)
  • Combining MPI process parallelism with OpenMP thread parallelism
  • Running HPC jobs with Slurm/PBS + mpirun
  • Debugging deadlocks and message mismatches
  • Parallel file I/O with MPI-IO

Workflow

1. Minimal MPI program

#include <mpi.h>
#include <stdio.h>

int main(int argc, char **argv) {
    MPI_Init(&argc, &argv);

    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    printf("Hello from rank %d of %d\n", rank, size);

    MPI_Finalize();
    return 0;
}
mpicc -o hello hello.c
mpirun -np 4 ./hello
# or
mpiexec -n 4 ./hello

2. Point-to-point

if (rank == 0) {
    int data = 42;
    MPI_Send(&data, 1, MPI_INT, 1, 0, MPI_COMM_WORLD);
} else if (rank == 1) {
    int recv;
    MPI_Recv(&recv, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    printf("rank 1 got %d\n", recv);
}

Tagged messages: match tag and source for MPI_Recv.

3. Collectives

int local = rank + 1;
int global_sum;

MPI_Allreduce(&local, &global_sum, 1, MPI_INT, MPI_SUM, MPI_COMM_WORLD);

// Broadcast
if (rank == 0) data = 100;
MPI_Bcast(&data, 1, MPI_INT, 0, MPI_COMM_WORLD);

// Scatter/Gather
MPI_Scatter(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT, 0, MPI_COMM_WORLD);
MPI_Gather(sendbuf, sendcount, MPI_INT, recvbuf, recvcount, MPI_INT, 0, MPI_COMM_WORLD);
CollectivePurpose
MPI_BcastOne-to-all
MPI_ScatterDistribute chunks
MPI_GatherCollect chunks
MPI_AllreduceReduce + broadcast result
MPI_BarrierSynchronization
MPI_AlltoallAll-to-all exchange

4. Non-blocking communication

MPI_Request req;
MPI_Isend(buf, count, MPI_INT, dest, tag, MPI_COMM_WORLD, &req);
// overlap computation here
do_local_work();
MPI_Wait(&req, MPI_STATUS_IGNORE);

// Multiple requests
MPI_Request reqs[2];
MPI_Irecv(buf0, n, MPI_INT, 0, 0, comm, &reqs[0]);
MPI_Irecv(buf1, n, MPI_INT, 1, 0, comm, &reqs[1]);
MPI_Waitall(2, reqs, MPI_STATUSES_IGNORE);

Overlap communication with computation to hide latency.

5. Subcommunicators

int color = rank / 4;  // groups of 4
MPI_Comm subcomm;
MPI_Comm_split(MPI_COMM_WORLD, color, rank, &subcomm);

int subrank, subsize;
MPI_Comm_rank(subcomm, &subrank);
MPI_Comm_size(subcomm, &subsize);

MPI_Comm_free(&subcomm);

6. MPI + OpenMP hybrid

#pragma omp parallel
{
    int tid = omp_get_thread_num();
    // thread-local work on rank's data partition
}
MPI_Barrier(MPI_COMM_WORLD);
MPI_Allreduce(...);
export OMP_NUM_THREADS=4
mpirun -np 8 --bind-to core ./hybrid_app
# 8 ranks × 4 threads = 32 cores

Bind ranks to sockets with --map-by ppr:2:socket.

7. Launching with hostfile

# hostfile:
# node0 slots=4
# node1 slots=4

mpirun -np 8 --hostfile hosts.txt ./app

# Slurm integration
srun -n 64 ./app
# or
mpirun -np $SLURM_NTASKS ./app
# Debug: tag output by rank
mpirun -np 4 --tag-output ./app

# Sequential debug (one rank at a time)
mpirun -np 4 -gdb ./app

8. MPI-IO

#include <mpi.h>

MPI_File fh;
MPI_File_open(MPI_COMM_WORLD, "output.dat",
    MPI_MODE_CREATE | MPI_MODE_WRONLY, MPI_INFO_NULL, &fh);

MPI_Offset offset = rank * chunk_size;
MPI_File_write_at(fh, offset, buf, count, MPI_DOUBLE, MPI_STATUS_IGNORE);

MPI_File_close(&fh);

Collective I/O for better performance:

MPI_File_write_at_all(fh, offset, buf, count, MPI_DOUBLE, MPI_STATUS_IGNORE);

9. Performance issues

Common bottlenecks
├── Load imbalance → dynamic scheduling (OpenMP) or redistribute MPI chunks
├── Serialization at rank 0 → tree-based reduce, parallel I/O
├── Excessive sync → replace Barrier with point-to-point where possible
├── Small messages → aggregate; use MPI_Pack or larger blocks
└── Alltoall on large process counts → consider MPI neighborhood collectives
# MPI profiling
mpiP  # lightweight profiler
# or IPM, TAU MPI wrappers

Common Problems

SymptomCauseFix
Hang at MPI_RecvTag/source mismatchCheck Send/Recv pairing; use MPI_ANY_TAG debug
DeadlockCircular waitReorder comm pattern; use non-blocking
Wrong result in AllreduceWrong datatype/countVerify MPI_INT vs MPI_DOUBLE
Poor scalingRank 0 bottleneckDistribute I/O and aggregation
MPI_ERR_TRUNCATEReceive buffer too smallMatch send/recv counts
Hybrid oversubscriptionToo many threads×ranksOMP_NUM_THREADS = cores/ranks

Related Skills

  • skills/hpc/openmp — thread-level parallelism within MPI ranks
  • skills/hpc/rdma-verbs — low-latency interconnect under MPI
  • skills/allocators/numa-programming — bind ranks to NUMA nodes
  • skills/profilers/linux-perf — profile MPI rank hotspots
  • skills/debuggers/gdb — debug individual MPI processes
  • skills/compilers/gcc — MPI compiler wrapper flags
Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/hpc/mpi

Default branch

main

Latest commit

bdc5847

Tree SHA

1178323