MPI-Jobs
Auf dem HPC-System sind verschiedene Compiler (GNU, Intel, Portland Group) und MPI-Umgebungen (MVAPICH, OpenMPI) installiert. Möchte man parallele Programme kompilieren und laufen lassen, sollte man sich zunächst für eine dieser Umgebungen entscheiden.
Beispiel 1: Auswahl des Intel Compilers und der MPI-Umgebung MVAPICH
Zunächst müssen die entsprechenden Module in die Systemumgebung des Nutzers eingefügt werden. Dies sollte in der Datei $HOME/.bashrc erfolgen, damit die Umgebung auf allen Rechenknoten identisch ist:
# Hinzufügen des Intel C/C++-Compilers:
module add intel/cce/10.1.008
# Hinzufügen des Intel Fortran-Compilers:
module add intel/fce/10.1.008
# Hinzufügen der OpenFabrics OFED Bibliothek (Infiniband):
module add ofed/1.3.1/base/64/1.3.1
# Hinzufügen der MVAPICH-Implementierung
# (mit Intel-Compiler übersetzt)
module add ofed/1.3.1/intel/mvapich/1.0.1
Zum Kompilieren von MPI-Programmen sollten die Compiler-Frontends mpicc (C), mpiCC (C++), mpif77 (Fortran77), mpif90 (Fortran90/95) verwendet werden. Neben den Optionen dieser Frontends (siehe z.B. man mpif90) können beim Kompilieren des Programms selbstverständlich auch die Optionen der Backend-Compiler (siehe z.B. man ifort) verwendet werden. Zum Beispiel zur Optimierung:
mpif90 -o programm.exe -tpp7 -xW -O3 -us -pad -funroll-loops -ip -ipo programm.f90
Angenommen, das fertige Programm programm.exe soll nun auf insgesamt 16 Cores (2 komplette HPC-Knoten, aber nicht zivsmp001) gerechnet werden. Als Rechenzeit werden weniger als ca. 40 Stunden erwartet. Dann könnte ein passendes PBS-Skript etwa so aussehen:
| #PBS -o output.dat | Name der Standardausgabe-Datei. Fehlt diese Zeile, wird per Default der Name des Jobfiles mit der Endung ".oJob-Id" angenommen. |
| #PBS -l walltime=40:00:00,nodes=2:hpc:ppn=8 | Maximale Dauer des Jobs. Nach dieser Zeit wird der Job abgebrochen. Es werden 2 HPC-Rechenknoten mit je 8 Cores zugeteilt. |
| #PBS -M username@uni-muenster.de | E-Mail-Adresse des Benutzers für Job-Benachrichtigungen. |
| #PBS -m bae | E-Mail soll generiert werden bei [b]egin, [a]bort, [e]nd des Jobs. |
| #PBS -q default | Die zu verwendende Queue: default, bigq, smallq, testq. Wegen der angeforderten 40 Stunden landet der Job in der Queue smallq. |
| #PBS -N Linpack |
Bis zu 15 Zeichen langer Name. |
| #PBS -j oe | Standardoutput und Standarderror sollen in die gleiche Datei geschrieben werden. |
| cp $PBS_NODEFILE $HOME/$PBS_JOBID.nodefile | Umkopieren der Knotendatei zu Diagnosezwecken. |
| mpirun -machinefile $PBS_NODEFILE -np 16 ./programm.exe | Start des MPI-Programms auf 16 Cores (./ ist eine Pfadangabe und steht für das aktuelle Verzeichnis, in diesem Fall das Heimatverzeichnis). |
Das fertige Skript kann dann mit qsub skript.pbs abgeschickt werden.
Beispiel 2: Hybrid-Programme (MPI/OpenMP)
Das von TORQUE erzeugte Nodefile eignet sich nur bedingt für die Verwendung bei MPI/OpenMP-Hybrid-Programmen. Üblicherweise wird man knotenübergreifend MPI und innerhalb eines Knotens OpenMP verwenden wollen, während im PBS_NODEFILE eine solche Unterscheidung nicht getroffen wird: Die Datei enthält nur eine Auflistung von Rechnernamen - für jeden angeforderten Core gibt es einen Eintrag. Man muss also selbst die Datei innerhalb des Batch-Skriptes den eigenen Bedürfnissen anpassen, indem man sie zum Beispiel sortiert und Duplikate entfernt (und auch gleich die Zeilen zählt):
NUMPROCS=`sort -ru $PBS_NODEFILE | tee nodefile.$PBS_JOBID | wc -l`
Dieses neu erzeugte Nodefile ist dann im nachfolgenden Aufruf von mpirun zu verwenden.
Außerdem hat die Default-MPI-Umgebung MVAPICH hat einen Nachteil: Hybrid-Programme, bei denen OpenMP zur Shared Memory-Programmierung innerhalb eines Rechenknotens und MPI für die knotenübergreifende Kommunikation verwendet wird, funktionieren nicht ohne weitere Maßnahmen.
MVAPICH verwendet CPU-Affinität, um bessere Performance für Single-Thread-Programme zu erreichen. Für Multi-Thread-Programme, wie beim MPI+OpenMP Hybrid-Modell, werden alle Threads eines Prozesses auf derselben CPU abgewickelt. In diesem Fall sollte CPU-Affinität abgeschaltet werden:
mpirun -np $NUMPROCS -machinefile nodefile.$PBS_JOBID VIADEV_USE_AFFINITY=0 ./a.out
Einfacher ist jedoch, gleich eine andere MPI-Implementierung zu verwenden, nämlich OpenMPI. Dazu ist in $HOME/.bashrc die Zeile
# module add ofed/1.3.1/intel/mvapich/1.0.1
auszukommentieren und statt dessen
module add ofed/1.3.1/intel/openmpi/1.2.6
zu verwenden. Nach dem nächsten Einloggen muss das Programm neu kompiliert werden. Es sollte dann wie erwartet mit mehreren aktiven Threads auf verschiedenen Cores laufen.
Stand: 19.3.2009