Measuring an MPI job¶
With srun¶
Install heapline once, from the source tree where you built it in the MPI tutorial:
cmake --install build --prefix $HOME/opt/heapline
The library goes to $HOME/opt/heapline/lib, or lib64 on some
distributions, such as RHEL, Rocky or SUSE, and heapline-report to
$HOME/opt/heapline/bin.
Prepare the output directory first: heapline does not create it.
#!/bin/bash
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=8
out=$SCRATCH/heapline/$SLURM_JOB_ID
mkdir -p "$out"
# libheapline.so is in lib (or lib64): check with ls $HOME/opt/heapline
srun env LD_PRELOAD=$HOME/opt/heapline/lib/libheapline.so \
HEAPLINE_OUTPUT=$out/heapline.%h.%r.csv ./app
$HOME/opt/heapline/bin/heapline-report "$out"
Pass LD_PRELOAD through env on the srun line rather than exporting it
in the script: exported, it would also preload heapline into srun and
every other command of the script.
./app must be the program itself. If it is a script that starts the real
program, read Wrapper processes first: the script is
preloaded too, and its record can replace the program’s.
The rank comes from SLURM_PROCID, set by srun for each task, unless the MPI
library sets one of its own variables (see the next section); a PMI variable
set by srun holds the same value.
With mpirun¶
mkdir -p records
mpirun -n 16 env LD_PRELOAD=$PWD/build/libheapline.so HEAPLINE_OUTPUT=$PWD/records/heapline.%h.%r.csv ./app
With Open MPI on a machine with fewer than 16 cores, add --oversubscribe
after mpirun (MPICH has no such option). With an installed copy, use the
path of the installed library instead of $PWD/build/libheapline.so. With the
RPM or the Debian package installed on every node, libheapline.so without a
path is enough (see Packages).
Keep env directly in front of the program. A script or /usr/bin/time
between them would be preloaded too, and its record can replace the program’s:
see Wrapper processes.
Open MPI sets OMPI_COMM_WORLD_RANK, MPICH and Intel MPI PMI_RANK,
MVAPICH MV2_COMM_WORLD_RANK, and PMIx-based launchers PMIX_RANK. heapline
reads OMPI_COMM_WORLD_RANK, PMIX_RANK, PMI_RANK, MV2_COMM_WORLD_RANK
and then SLURM_PROCID, in this order, and takes the first one that is set.
SLURM_PROCID comes last because the ranks started by mpirun inside a Slurm
allocation inherit the SLURM_PROCID of the process that started them: 0 on
the first node, and the index of the node’s daemon on the other nodes. Either
way it is not their rank.
Wrapper processes¶
LD_PRELOAD reaches every process started by the preloaded command. A shell
script run without exec, /usr/bin/time or any other process that stays the
parent of the program is preloaded too. It has the same rank and host as the
program and usually exits last, so with HEAPLINE_OUTPUT=heapline.%h.%r.csv
its record overwrites the program’s, and nothing warns you.
There are two ways to avoid it:
Start the program with
execin wrapper scripts, and putLD_PRELOADon the program itself rather than on the wrapper. The last line of the script becomesexec env LD_PRELOAD=... HEAPLINE_OUTPUT=... ./app.Or add
%pto the file name, as inheapline.%h.%r.%p.csv. Every process then keeps its own record.heapline-reportshows both, and its warning about duplicate ranks names the two files, the wrapper’s among them. Remove the wrapper’s file before reading the figures: its small record lowers the minimum and shifts the median and the imbalance.
Sizing –mem¶
heapline-report prints, per node, the sum of VmHWM of its ranks. Compare
the largest one with the --mem request, which applies per node, and keep a
margin for the page cache and the system.
--mem-per-cpu is also enforced per node: the limit is the request times the
CPUs allocated on the node. Comparing it with the same per-node sum is
therefore the like-for-like check. Comparing the largest VmHWM of a rank with
the request times the CPUs of a task is a stricter one.