Performance Optimization/Multiple nodes (MPI): Difference between revisions

From HPCwiki
Jump to navigation Jump to search
Megen002 (talk | contribs)
No edit summary
 
(13 intermediate revisions by 4 users not shown)
Line 1: Line 1:
MPI (the Message Passing Interface) lets a single program run across many cores, and even many nodes, at once by passing messages between its processes. Use it for software written to scale beyond one node. To use several cores within a single node, see [[Performance Optimization/Multiple CPUs]]; for many independent tasks, see [[Performance Optimization/Multiple nodes (arrayjobs)]].


<source lang='cpp'>
== Compiling an MPI program ==
 
Load a software bucket, then a compiler and an MPI library, through the module system. A bucket has to be loaded before its modules are visible (see [[Environment Modules]]). To avoid library conflicts it is safest to start from a clean environment — note that purging also removes the <code>slurm</code> module, so reload it:
 
<syntaxhighlight lang="bash">
module purge
module load 2025
module load OpenMPI/5.0.7
</syntaxhighlight>
 
As a simple example, here is the classic MPI "Hello World" in C:
 
<syntaxhighlight lang="c">
#include <stdio.h>
#include <stdio.h>
#include <mpi.h>
#include <mpi.h>
int main(int argc, char ** argv) {
int main(int argc, char **argv) {
  int size,rank,namelen;
    int size, rank, namelen;
  char processor_name[MPI_MAX_PROCESSOR_NAME];
    char processor_name[MPI_MAX_PROCESSOR_NAME];
  MPI_Init(&argc, &argv);
    MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD,&rank);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD,&size);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
  MPI_Get_processor_name(processor_name, &namelen);
    MPI_Get_processor_name(processor_name, &namelen);
  printf("Hello MPI! Process %d of %d on %s\n", rank, size, processor_name);
    printf("Hello MPI! Process %d of %d on %s\n", rank, size, processor_name);
  MPI_Finalize();
    MPI_Finalize();
}
}
</source>
</syntaxhighlight>


<source lang='bash'>
Compile it with the MPI compiler wrapper:
module list
</source>


<source lang='bash'>
<syntaxhighlight lang="bash">
module purge
mpicc hello_mpi.c -o hello_mpi
</source>
</syntaxhighlight>
 
== Running an MPI program ==
 
Launch the MPI processes with <code>srun</code>, which spreads them across the nodes your job was allocated. For example, two nodes with four tasks each:


<source lang='bash'>
<syntaxhighlight lang="bash">
module load gcc/4.8.1 openmpi/gcc/64/1.6.5 slurm/2.5.7
srun --nodes=2 --ntasks-per-node=4 ./hello_mpi
</source>
</syntaxhighlight>


<source lang='bash'>
In a batch job, request the nodes and tasks with <code>#SBATCH</code> and launch with <code>srun</code>:
mpicc hello_mpi.c -o test_hello_world
</source>


<source lang='bash'>
<syntaxhighlight lang="bash">
ldd test_hello_world
#!/bin/bash
</source>
#SBATCH --job-name=mpi-test
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=4
#SBATCH --time=00:30:00
#SBATCH --output=mpi-%j.out


  linux-vdso.so.1 =>  (0x00002aaaaaacb000)
module purge
  libmpi.so.1 => /cm/shared/apps/openmpi/gcc/64/1.6.5/lib64/libmpi.so.1 (0x00002aaaaaccd000)
module load 2025
  libdl.so.2 => /lib64/libdl.so.2 (0x00002aaaab080000)
module load OpenMPI/5.0.7
  libm.so.6 => /lib64/libm.so.6 (0x00002aaaab284000)
srun ./hello_mpi
  libnuma.so.1 => /usr/lib64/libnuma.so.1 (0x0000003e29400000)
</syntaxhighlight>
  librt.so.1 => /lib64/librt.so.1 (0x00002aaaab509000)
  libnsl.so.1 => /lib64/libnsl.so.1 (0x00002aaaab711000)
  libutil.so.1 => /lib64/libutil.so.1 (0x00002aaaab92a000)
  libpthread.so.0 => /lib64/libpthread.so.0 (0x00002aaaabb2e000)
  libc.so.6 => /lib64/libc.so.6 (0x00002aaaabd4b000)
  /lib64/ld-linux-x86-64.so.2 (0x00002aaaaaaab000)


<source lang='bash'>
<!-- TODO: confirm the recommended MPI library and module names for the current cluster, any required `srun --mpi=...` plugin flag, and whether specific interconnect/fabric tuning is needed. The previous page documented an mvapich2 + InfiniBand (ib0) setup from the Breed4Food cluster, which may no longer match Anunna's hardware. -->
srun --nodes=2 --ntasks-per-node=4 --partition=ABGC --mpi=openmpi ./test_hello_world
</source>


  Hello MPI! Process 4 of 8 on node011
== See also ==
  Hello MPI! Process 1 of 8 on node010
* [[Performance Optimization/Multiple CPUs]]
  Hello MPI! Process 7 of 8 on node011
* [[Performance Optimization/Multiple nodes (arrayjobs)]]
  Hello MPI! Process 6 of 8 on node011
* [[Environment Modules]]
  Hello MPI! Process 5 of 8 on node011
* [[Batch Jobs]]
  Hello MPI! Process 2 of 8 on node010
* [[Scheduler Overview (Slurm)]]
  Hello MPI! Process 0 of 8 on node010
* [[Cluster Architecture Overview]]
  Hello MPI! Process 3 of 8 on node010

Latest revision as of 11:34, 21 July 2026

MPI (the Message Passing Interface) lets a single program run across many cores, and even many nodes, at once by passing messages between its processes. Use it for software written to scale beyond one node. To use several cores within a single node, see Performance Optimization/Multiple CPUs; for many independent tasks, see Performance Optimization/Multiple nodes (arrayjobs).

Compiling an MPI program

Load a software bucket, then a compiler and an MPI library, through the module system. A bucket has to be loaded before its modules are visible (see Environment Modules). To avoid library conflicts it is safest to start from a clean environment — note that purging also removes the slurm module, so reload it:

module purge
module load 2025
module load OpenMPI/5.0.7

As a simple example, here is the classic MPI "Hello World" in C:

#include <stdio.h>
#include <mpi.h>
int main(int argc, char **argv) {
    int size, rank, namelen;
    char processor_name[MPI_MAX_PROCESSOR_NAME];
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Get_processor_name(processor_name, &namelen);
    printf("Hello MPI! Process %d of %d on %s\n", rank, size, processor_name);
    MPI_Finalize();
}

Compile it with the MPI compiler wrapper:

mpicc hello_mpi.c -o hello_mpi

Running an MPI program

Launch the MPI processes with srun, which spreads them across the nodes your job was allocated. For example, two nodes with four tasks each:

srun --nodes=2 --ntasks-per-node=4 ./hello_mpi

In a batch job, request the nodes and tasks with #SBATCH and launch with srun:

#!/bin/bash
#SBATCH --job-name=mpi-test
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=4
#SBATCH --time=00:30:00
#SBATCH --output=mpi-%j.out

module purge
module load 2025
module load OpenMPI/5.0.7
srun ./hello_mpi


See also