Inhalt des Dokuments
zur Navigation
Benutzung
Login-Hosts
Batch-System
Format eines Job-Scripts
Jobs mit grossem Memory-Bedarf, Multi-Threaded Programme
Überprüfen der Queues und der Clusternutzung
Ändern und Löschen von Jobs
Array jobs
Diskplatz
Parallele Programme mit MPI
Entwicklungswerkzeuge
Entwicklungswerkzeuge für MPI-Programme
Relevante Manual-Pages
Login-Hosts
Als Login-Hosts stehen die Rechner
- cluster-a.math.tu-berlin.de
- cluster-i.math.tu-berlin.de
- cluster-g.math.tu-berlin.de
- cluster-v.math.tu-berlin.de
- cluster-x.math.tu-berlin.de
zur Verfügung.
Die allgemeine Adresse
- cluster.math.tu-berlin.de
zeigt auf einen der o.g. Login-Hosts (derzeit immer cluster-i).
cluster-a ist ein AMD-basierter Rechner, cluster-i läuft mit Intel-Prozessoren. Für's normale Arbeiten und Job-Submittieren spielt dies keine Rolle, einige Compiler optimieren jedoch für die jeweils aktuelle Hardware-Konfiguration.
Auf den Login-Rechnern bitte nicht rechnen, sie dienen nur zum Editieren und Abschicken von Jobs (s.u.).
Bei cluster-g handelt es sich um einen Intel-Knoten, der darüber hinaus über 2 Tesla C1060 GPU-Karten verfügt. näheres dazu in dem Abschnitt zum GPU-Cluster.
Zugriff auf die /scratch-Disks der Cluster-Knoten ist möglich via den Pfad:
/net/<nodename>.scratch/ |
also z.B.
% ls /net/node008.scratch/ |
Batch-System
Die Cluster laufen derzeit aussschliesslich als Batch-System, d.h. Jobs werden als Job-Script formuliert und mit 'qsub' abgeschickt.
Ein kleines Job-Script kann man z.B. wie folgt erzeugen und abschicken:
% cat > myjob.job <<EOF |
Statt 'cat' kann natürlich auch ein beliebiger Texteditor zur Erstellung des Job-Files benutzt werden.
Der Job läuft an, wenn irgendwo die geforderten Ressourcen frei sind. Das kann sofort sein, bei speziellen Anforderungen aber auch Tage dauern. Der Benutzer kann sich über Email informieren lassen, ob Jobs gestartet, beendet oder abgebrochen wurd
Format eines Job-Scripts
Noch einmal das obige Beispiel mit Zeilennummern und ein paar mehr Parameter-Zeilen:
1 #!/bin/bash --login |
Erläuterung:
2) Wechselt ins Verzeichnis, aus dem der Job abgeschickt wurde.
3) Jobname
4) Output-File
5) 'Join'=yes, d.h. Errors zusammen mit Output ins Output-File
6) Angabe der maximalen Laufzeit ('hard real time', in Sekunden).
7) Mail bei Beginn und Ende des Jobs schicken
8) Mail-Adresse (bitte angeben !!)
Die Angabe der maximalen Laufzeit wird dringend empfohlen. Der Cluster-Scheduler wird zum einen kurze Jobs bevorzugen und zum anderen existieren für einige Queues Laufzeitlimiten, teilweise bis hinunter zu 1 Stunde. Die maximale Laufzeit liegt zur Zeit bei 220 Stunden (Stand 11/2010). Längere Laufzeiten sind auf Antrag möglich.
Des weiteren besteht eine Obergrenze für die Memory-Allocation damit weitere Prozessoren und jeweils die andere Hälfte des Speichers noch für andere Jobs verwendet werden können. Siehe unten für Möglichkeiten, mehr Memory zu nutzen. Welche Grenze festgelegt ist, hängt davon ab, welcher Cluster genutzt wird. Eine Anforderung im Job Script betr. freiem Memory wirkt sich damit auch auf die Selektion des Clusters aus (Siehe Beispiel unten).
Sämtliche Job-Parameter, die in einem Script benutzt werden können, dürfen auch auf der Kommandozeile von qsub benutzt werden und haben dann höhere Priorität:
% qsub -N test -l h_rt=80000 -l mem_free=4G jobscript |
Die verfügbaren Parameter lassen sich durch einen Aufruf von
% qconf -sc |
anzeigen.
Jobs mit grossem Memory-Bedarf, Multi-Threaded Programme
Programme, die das ganze Memory von 4GB (rsp. 16GB oder 32GB) nutzen wollen oder mit mehreren Threads oder Prozessen arbeiten, sollten jeweils eine Cluster-Node mit mehreren Prozessoren komplett reservieren. Dies erreicht man mit der zusätzlichen Zeile
#$ -l exclusive |
im Job-Script.
Der Job läuft dann auf einem freien Cluster-Knoten (sobald einer frei ist!). Welcher Art dieser Knoten ist wird von weiteren Selektions-Flags eingeschränkt (so vorhanden).
Überprüfen der Queues und der Clusternutzung
Das Kommando qstat zeigt die laufenden und wartenden Jobs an:
% qstat |
Optionen wie '-u username' oder '-s r' schränken die Liste ein. Siehe 'man qstat'.
Ändern und Löschen von Jobs
Einige der Job-Parameter können auch nach dem Abschicken des Jobs noch geändert werden, teilweise sogar noch wenn der Job schon läuft. Hierzu dient das Kommando qalter. Es kennt im Wesentlichen dieselben Optionen wie qsub und setzt die entsprechenden Parameter für die angegebene Job-ID. Jobs, die falsch aufgesetzt, abgeschickt oder sonstwie beseitigt werden sollen, werden mit dem Kommando qdel unter Angabe der Job-ID entfernt. Beispiel:
|
Array jobs
Es kommt ab und zu vor, dass ein Job-Script mit einer grossen Anzahl Datensätzen laufen soll und dies im Prinzip auch parallel tun könnte. Die offensichtliche Methode, nämlich einfach n nur leicht differierende Job-Scripts zu schreiben und abzuschicken, ist sicherlich ab n > 3 eher lästig. Eine elegantere Lösung sind sog. Job-Arrays, wo ein einziges Job-Script abgeschickt wird, versehen mit der Weisung in n Kopien zu starten. Ein entsprechendes qsub Kommando sieht so aus:
% qsub -t 10-30:2 jobscript |
Das obige Kommando schickt das Script jobscript ins Batch-System und erzeugt dort 11 Kopien, die jeweils eine sog. TASK_ID zugewiesen bekommen im Bereich [10..30] mit Abstand 2, also 10 12 14 16 ....
Im Job-Script steht die Task-ID an zwei Stellen zur Verfügung:
1) Im Script-Header:
Hier können z.B. die Namen der Output-Files um die Task-ID ergänzt werden, so dass jede Kopie in ein eigenes File schreibt:
#$ -o job.$TASK_ID.out |
2) Im Script selbst:
Hier steht die Task-Id in der Environment-Variable $SGE_TASK_ID und kann im Script selbst oder in von dort gestarteten Prozessen gelesen und genutzt werden.
#!/bin/bash --login |
Hier noch ein Beispiel für einen Matlab-Input, der die Task-ID direkt liest:
task_id = str2num( getenv('SGE_TASK_ID') ) |
Diskplatz
Jobs bekommen ein temporäres Verzeichnis zugewiesen, in dem vom Job erzeugte Files abgelegt werden können. Das Verzeichnis erreicht man über die Variable $TMPDIR. Es befindet sich auf der lokalen Festplatte des Knotens, auf dem der job ausgeführt wird und wird am Ende des Jobs gelöscht, wertvolle Daten sind von dort also am Ende des Jobs wegzukopieren.
Kleinere Mengen Daten können im Home-Verzeichnis gelagert werden und werden dort jede Nacht gesichert. Die Anfangs-Quota ist relativ restriktiv. Bitte melden, falls der Platz nicht ausreicht !
Für grössere Datenmengen gibt es das Verzeichnis /work/$USER.
ACHTUNG: Dieses Verzeichnis ist nicht im täglichen Backup enthalten !
Ausserdem existiert das Verzeicnis /lustre, das ähnlich wie /work dimensioniert ist, aber deutlich schneller sein sollte. Hier können bei der Verarbeitung eines jobs entstehende grosse Datenmengen schnell und ohne Belastung der für das /work-Verzeichnis zuständigen fileserver gespeichert werden.
Allerdings ist /lustre nur für temporäre Speicherung von Daten gedacht. Die Systembetreuung behält sich das Recht vor, dort ältere Dateien von Zeit zu Zeit löschen.
Parallele Programme mit MPI
Für paralle Programme mit MPI sollte man ein Job-Script ähnlich dem folgenden benutzen:
#!/bin/bash --login |
Die '4' gibt hier die gewünschte Anzahl Prozessoren an. Es kann sogar ein Bereich von Prozessoren gewünscht werden:
#$ -pe ompi* 2-8 |
was den Job mit zwischen 2 und 8 Prozessoren startet (je nachdem was frei ist). Die tatsächlich alloziierte Anzahl ist im Script dann über die Variable $NSLOTS abrufbar.
Die sog. "Parallel Environments" ompi*, wie in den obigen Beispielen mit -pe angefordert werden, sind eine Art Gruppierung für die eigentlichen Queues. Sie bestimmen bei Anforderung von mehr als einem Queue-Slot, ob und wie die Prozesse auf die Knoten verteilt werden. Wegen der Netzwerktopologie der beiden Cluster gibt es eine ganze Reihe dieser ompi* PEs, das '*' in der oben gezeigten Anforderung bedeutet: Nimm irgendeines dessen Name mit 'ompi' anfängt.
Die folgende Liste zeigt das Schema, nach dem die PEs benannt sind:
PE-Name | Cluster | Prozesse/Knoten |
---|---|---|
mp | * | n |
mpi1 | * | 1 |
mpi2 | * | 2 |
mpi4 | * | 4 |
mpi | * | fill |
ompi1_1 | 1 | 1 |
ompi1_2 | 1 | 2 |
ompi1_n | 1 | fill |
ompi2_1 | 2 | 1 |
ompi2_2 | 2 | 2 |
ompi2_4 | 2 | 4 |
ompi2_n | 2 | fill |
ompi3_1 | 3 | 1 |
ompi3_2 | 3 | 2 |
ompi3_4 | 3 | 4 |
ompi3_n | 3 | fill |
usw.... |
Was man hier ggf. noch zu wissen braucht, ist die Anzahl Slots / Knoten in jedem Cluster:
Cluster | Slots/Knoten |
---|---|
1 | 2 |
2 | 4 |
3 | 4 |
4 | 4 |
5 | 2 |
6 | 16 |
7 | 8 |
8 | 8 |
9 | 4 |
10 | 8 |
11 | 12 |
12 | 8 |
In obiger PE-Liste bedeutet:
n | So wie angegeben |
fill | Ein Knoten bekommt so viele Prozesse wie Platz ist, dann kommt der nächste Knoten dran. |
* | egal |
Das -pe kann also auch so aussehen:
#$ -pe mpi1 2-8 |
Für Programme, die mit OpenMPI kompiliert wurden, sollten NUR die ompi* PEs benutzt werden.
Die PEs mit Namen 'mpi*' sind für Programme, die ein Ethernet-basiertes MPI verwenden. Eine Liste der Hostnamen findet sich im File
$PE_HOSTFILE |
Entwicklungswerkzeuge
Für den Cluster und die anderen 64bit-Rechner im Institut wurden eine Reihe von zusätzlichen Compilern installiert, die, was die Optimierung für Opteron-Prozessoren angeht, eine höhere Performance versprechen als die normalen gcc Versionen.
Hier eine Übersicht:
Hersteller | Name des Compilers | Sprache | Installierte Versionen | Modul |
---|---|---|---|---|
GNU | gcc | C89, C991 | 4.3.3 | |
g++ | ISO C++ 89 | 4.3.3 | ||
g77 | Fortran77 | 4.3.3 | ||
gfortran | Fortran77, Fortran90 | 4.3.3 | ||
Intel | ifort | Fortran77, Fortran901 | 9.0.25, 9.1.36, 10.1.018, 11.0.069, 11.1.064 | ifc-* |
icc | C89, C901 | 9.0.23, 9.1.42, 10.1.018, 11.0.069, 11.1.064 | icc-* | |
icpc | ISO C++ 89 | 9.0.23, 9.1.42, 10.1.018, 11.0.069, 11.1.064 | icc-* | |
PathScale2) | pathCC | ISO C++ 89 | 2.0, 2.1, 2.2.1, 2.3, 2.3.1, 2.4, 2.5, 3.0, 3.1, 3.2 | pathscale-* |
pathcc | ISO C89, C99 | |||
pathf77 | Fortran77 | |||
pathf90 | Fortran90 | |||
path95 | Fortran95 | |||
Portland | pgcc | C89 | 8.0-2, 8.0-6, 9.0-1, 10.0 | pgi-* |
pgCC | ISO C++ 89 | |||
pgf77 | Fortran77 | |||
pgf90 | Fortran90 | |||
pgf95 | Fortran95 |
1teilweise.
2Für die Pathscale-Compiler gibt es keine Lizenzen mehr, die Laufzeitumgebung kann aber noch genutzt werden.
Nicht alle Compiler sind im normalen Suchpfad vorhanden. Wenn eine spezielle Version benötigt wird, können die entsprechenden Environment-Variablen mit dem module Kommando gesetzt werden. Beispiel:
% module add pathscale-2.2.1 |
Der Name des Moduls kann der obigen Tabelle entnommen werden und wird mit der entsprechenden Versionsnummer ergänzt. Mit module avail erhält man eine Liste der verfügbaren Module:
% module avail |
Nicht alle aufgelisteten Module betreffen Compiler. Informationen zu einem bestimmten Modul erhält man mit (z.B.):
% module help pgi-6.0.5 |
Bei häufiger Benutzung bestimmter Module ist es sinnvoll, entsprechende module-Befehle im ~/.cshrc- oder ~/.bashrc-File unterzubringen. Beispiel:
% tail ~/.cshrc |
Entwicklungswerkzeuge für MPI-Programme
Für die Compilierung von MPI-Programmen sollte man die jeweiligen MPI-Compiler-Wrapper mpicc, mpif77 etc. benutzen, die einen der oben genannten Compiler aufrufen und die korrekten MPI-Bibliotheken dazulinken.
Eine Default-Version von OpenMPI ist bereits in den Pfaden enthalten, andere Versionen sind über Module verfügbar.
Die hierfür relevanten Module heissen:
Modul | Inhalt |
---|---|
ompi-gcc-1.2.2 | OpenMPI 1.2.2 für gcc |
ompi-pgi-1.2.2 | OpenMPI 1.2.2 für Portland |
ompi-gcc-1.2.4 | OpenMPI 1.2.4 für gcc |
ompi-pgi-1.2.4 | OpenMPI 1.2.4 für Portland |
ompi-gcc-1.3.2 | OpenMPI 1.3.2 für gcc |
ompi-pgi-1.3.2 | OpenMPI 1.3.2 für Portland |
Die Kompilation von MPI-Programmen geht dann nach folgendem Muster:
% mpicc -o myprog myprog.c |
% mpif90 -o myprog myprog.f |