Fullmoon System

Open MPI einrichten: Kompilieren, SSH, Slurm und Leistungstests

EdwardMoon

Open MPI einzurichten bedeutet mehr, als dieselbe Programmdatei auf alle Knoten zu kopieren. Compiler- und Open-MPI-Version, Laufzeitbibliotheken, Netzwerktransportschicht und Scheduler-Integration müssen zusammenpassen. Prüfen Sie die Umgebung schrittweise: zunächst mit einem kleinen Programm, anschließend mit Messungen der Kommunikationsleistung.

Dieser Leitfaden behandelt die Wahl zwischen Distributionspaketen und offiziellem Tarball, Compiler-Wrapper, SSH-Starts ohne Scheduler, mpirun innerhalb einer Slurm-Zuweisung, PMIx und PRRTE sowie die Prüfung von CPU-Bindung und UCX im Betrieb.

Open-MPI-Ablauf: Compiler-Wrapper, Slurm-Zuweisung, mpirun mit PMIx und PRRTE sowie MPI-Ranks auf Rechenknoten
Ein mit einem Compiler-Wrapper gebautes Programm innerhalb einer Slurm-Zuweisung mit mpirun, PMIx und PRRTE ausführen

Das passende Ausführungsmodell wählen

Umgebung Empfohlener Start Voraussetzungen
Entwicklung auf einem einzelnen Host mpirun -n Lokale Bibliotheken und verfügbare Slots
Kleiner Cluster ohne Scheduler mpirun + hostfile SSH, identische Pfade und geprüfte Hostschlüssel
Produktiver Slurm-Cluster mpirun innerhalb der Ressourcenzuweisung Build mit Slurm-/PMIx-Integration und passende Ressourcenrichtlinien
Umgehen Sie in einem produktiven Slurm-Cluster die Ressourcenverwaltung nicht mit beliebigen Hostdateien und direkten SSH-Starts auf Rechenknoten. Jobs außerhalb einer Scheduler-Zuweisung beeinträchtigen die Isolation von CPU, Arbeitsspeicher und GPU sowie die Aufzeichnung der Ressourcennutzung.

Distributionspakete oder Quellcode-Build

Distributionspakete vereinfachen Updates und die Verwaltung von Abhängigkeiten. Ihre Version oder UCX-/PMIx-Unterstützung erfüllt jedoch möglicherweise nicht alle Anforderungen. Prüfen Sie deshalb zunächst die Paketinformationen. Bauen Sie erst bei fehlenden Funktionen einen offiziellen Open-MPI-Release-Tarball unter einem eigenen Installationspräfix. Von GitHub automatisch erzeugte Quellcodearchive ersetzen den offiziellen Release-Tarball nicht.

dnf info openmpi openmpi-devel
rpm -q openmpi openmpi-devel
module avail 2>&1 | grep -i mpi

Den offiziellen Tarball prüfen und unter einem eigenen Präfix bauen

sha256sum -c openmpi-X.Y.Z.tar.bz2.sha256
tar -xjf openmpi-X.Y.Z.tar.bz2
cd openmpi-X.Y.Z

./configure   --prefix=/opt/openmpi/X.Y.Z   --with-slurm   --with-pmix   --with-ucx
make -j"$(nproc)"
make check
sudo make install

Prüfen Sie in der configure-Zusammenfassung, ob die angeforderten Funktionen tatsächlich erkannt wurden. Liegen UCX oder PMIx auf unterschiedlichen Pfaden, kann die automatische Erkennung auf den einzelnen Knoten verschiedene Bibliotheken einbinden. Im Betrieb verbessert die Verteilung desselben RPM-Pakets die Reproduzierbarkeit.

/opt/openmpi/X.Y.Z/bin/ompi_info --version
/opt/openmpi/X.Y.Z/bin/ompi_info --all   | grep -Ei 'slurm|pmix|prrte|ucx'
ldd /opt/openmpi/X.Y.Z/bin/mpirun

Umgebungsmodule und einheitliche Knoten

Eine passende PATH-Variable allein genügt nicht. Die von den Compiler-Wrappern verwendeten Header und Bibliotheken sowie die Laufzeitpfade für libmpi und Plugins müssen auf allen Knoten übereinstimmen.

export PATH=/opt/openmpi/X.Y.Z/bin:$PATH
export LD_LIBRARY_PATH=/opt/openmpi/X.Y.Z/lib:$LD_LIBRARY_PATH

which mpicc
which mpirun
mpicc --showme:command
mpicc --showme:compile
mpicc --showme:link
ompi_info --version
for host in node01 node02 node03 node04; do
  ssh "$host" '/opt/openmpi/X.Y.Z/bin/ompi_info --version'
done
Umgebungsmodule erleichtern Versionswechsel und reproduzierbare Abläufe. Eine Moduldatei sollte PATH und Bibliothekspfade ausschließlich auf das Installationspräfix einer bestimmten Version verweisen lassen. Laden Sie die benötigte Version im Jobskript ausdrücklich.

Ein minimales MPI-Programm mit einem Compiler-Wrapper bauen

mpicc und mpicxx sind keine eigenständigen Compiler. Sie ergänzen den ausgewählten C-/C++-Compiler um die erforderlichen MPI-Optionen. Stellen Sie Header- und Bibliothekspfade daher nicht manuell für einen gewöhnlichen gcc-Aufruf zusammen.

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

int main(int argc, char **argv) {
    int rank, size, name_len;
    char 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(name, &name_len);
    printf("rank=%d size=%d host=%s\n", rank, size, name);
    MPI_Finalize();
    return 0;
}
mpicc -O2 -Wall -Wextra hello_mpi.c -o hello_mpi
ldd ./hello_mpi | grep -E 'libmpi|open-rte|pmix'
mpirun -n 4 ./hello_mpi
Führen Sie Open MPI nicht als root aus. Verwenden Sie auch in Containern einen eigenen unprivilegierten Benutzer und die Ressourcenbegrenzungen des Schedulers. Optionen, die eine Ausführung als root erzwingen, gehören nicht zum regulären Betriebsverfahren.

SSH-Start in einem Cluster ohne Scheduler

Verwenden Sie eine Hostdatei nur in einem Testcluster ohne Scheduler. Programmdatei und dynamische Bibliotheken müssen auf allen Knoten unter denselben absoluten Pfaden vorhanden sein. SSH-Schlüsselauthentifizierung und Hostschlüsselprüfung müssen bereits funktionieren.

node01 slots=8
node02 slots=8
mpirun --hostfile hosts.txt   --map-by ppr:4:node   --bind-to core   ./hello_mpi

Starten Sie nicht unbeabsichtigt mehr Ranks als verfügbare Slots. Eine Überbelegung (Oversubscription) kann für Entwicklungstests gezielt eingesetzt werden, verfälscht jedoch möglicherweise Leistungsmessungen und erhöht den Speicherdruck.

mpirun innerhalb einer Slurm-Zuweisung verwenden

Für Open MPI 5 wird auch unter Slurm die Verwendung von mpirun empfohlen. Innerhalb einer Ressourcenzuweisung liest mpirun die von Slurm bereitgestellten Knoten- und Task-Informationen. Hostdatei, –host und -n müssen deshalb nicht erneut angegeben werden.

#!/usr/bin/env bash
#SBATCH --job-name=mpi-smoke
#SBATCH --partition=compute
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=4
#SBATCH --cpus-per-task=1
#SBATCH --time=00:05:00
#SBATCH --output=mpi-%j.out

set -euo pipefail
module purge
module load openmpi/X.Y.Z

echo "nodes=${SLURM_JOB_NODELIST} tasks=${SLURM_NTASKS}"
mpirun --bind-to core --map-by slot ./hello_mpi
JOB_ID=$(sbatch --parsable mpi-smoke.sbatch)
squeue --job "$JOB_ID"
sacct --jobs "$JOB_ID"   --format=JobID,State,Elapsed,AllocCPUS,ExitCode
cat "mpi-${JOB_ID}.out"

Direkten Start mit srun erst nach Prüfung der PMIx-Unterstützung wählen

Ein direkter Start mit srun ist ebenfalls möglich, setzt jedoch voraus, dass Slurm und Open MPI mit kompatibler PMIx-Unterstützung gebaut wurden. Prüfen Sie zunächst die verfügbaren Plugins und dokumentieren Sie einheitlich, ob Ihre Umgebung mpirun oder srun als Standard verwendet.

srun --mpi=list
ompi_info --all | grep -Ei 'pmix|slurm'
srun --mpi=pmix ./hello_mpi

TCP, UCX und CPU-Bindung prüfen

Bei Ethernet kann TCP, bei InfiniBand oder RoCE kann UCX zum Einsatz kommen. Erzwingen Sie die Transportschicht nicht ungeprüft. Kontrollieren Sie zuerst die von Open MPI erkannte Konfiguration, den NIC-Zustand, die MTU und die Zugriffsrechte auf RDMA-Geräte.

ompi_info --param pml all
ompi_info --param btl all
ompi_info --param osc all
ucx_info -d
ibv_devinfo
ip -br link
mpirun --report-bindings   --display-map   --bind-to core   --map-by slot   ./hello_mpi

Messen Sie auf Knoten mit Hyperthreading, NUMA oder GPUs die Wirkung von map-by und bind-to anhand der tatsächlichen Anwendung. Überschreiten Sie die Anzahl physischer Kerne nicht unter der pauschalen Annahme, mehr Ranks würden automatisch mehr Leistung liefern.

Funktion und Leistung getrennt testen

  1. Initialisierung und Beendigung mit zwei bis vier Ranks auf einem einzelnen Knoten prüfen.
  2. Mit einem Hello-Programm auf zwei Knoten die Namensauflösung und den Prozessstart prüfen.
  3. Latenz und Bandbreite mit einem kleinen Ping-Pong-Benchmark erfassen.
  4. CPU-, Speicher- und Netzwerknutzung sowie Skalierbarkeit mit echten Anwendungseingaben messen.
  5. Prüfen, dass nach Knoten- oder NIC-Ausfällen und nach Job-Abbrüchen keine Prozesse zurückbleiben.
mpirun -n 2 osu_latency
mpirun -n 2 osu_bw
sstat --jobs "${SLURM_JOB_ID}.batch"   --format=JobID,AveCPU,MaxRSS,AveRSS

Fehlerbehebung

mpirun --version
mpicc --showme
ompi_info --version
ldd ./hello_mpi
env | grep -E '^(PATH|LD_LIBRARY_PATH|OPAL|OMPI|PMIX|PRTE|SLURM)'
scontrol show job "$SLURM_JOB_ID"
hostnamectl --static
getent hosts node01
  • Bei unterschiedlichen libmpi-Versionen die Module und LD_LIBRARY_PATH bereinigen und denselben Build erneut verteilen.
  • Bei fehlgeschlagenen Remote-Starts Hostschlüssel, nichtinteraktives SSH, identische Pfade und Firewall prüfen.
  • Wenn Slurm-Jobs Knoten außerhalb ihrer Zuweisung verwenden, Hostdatei und –host-Optionen entfernen.
  • Bei UCX-Fehlern Geräte, Treiber, MTU, Speicher-Locking und Geräteberechtigungen in Containern prüfen.
  • Bei Leistungseinbußen CPU-Bindung, NUMA, Überbelegung und das Kommunikationsmuster der Anwendung gemeinsam untersuchen.

Offizielle Dokumentation und weitere Artikel

Eine Open-MPI-Umgebung ist nicht allein durch einen erfolgreichen Hello-Test einsatzbereit. Einheitliche Builds, Einhaltung der Scheduler-Zuweisungen, Bindung, Transportschicht, Aufzeichnung der Ressourcennutzung und tatsächliche Leistung müssen reproduzierbar funktionieren. Halten Sie Versionen, Module, Compiler-Optionen und Benchmark-Ergebnisse fest, um den Zustand vor und nach Upgrades vergleichen zu können.