Eine Frage zur grundsätzlichen Arbeit mit Slurm und einem Cluster

Peter_2498

Lieutenant
Registriert
Apr. 2018
Beiträge
618
Ich arbeite gerade an einem Projekt an der Uni, wo ich bald meinen Python-Code auf so einem Knoten laufen lassen kann, weil mein PC viel zu langsam für die Berechnungen ist.

Ich hab bisher noch nie mit sowas gearbeitet und ich bin gerade dabei mich mit dem ganzen Job-Scheduling vertraut zu machen.

Bisher hab ich eigentlich immer alle Berechnungen über ein einziges Skript gestartet. Jetzt sind aber die einzelnen Berechnungen viel viel aufwendiger und von einem wird auch erwartet, dass man die Ressourcen vom Cluster effizient nutzt, was ich absolut verstehen kann. Man will ja nicht, dass eine 96 Kerne CPU von einem Programm blockiert wird, welches 8 Kerne nutzt..

Sehe ich das jetzt richtig, dass ich eigentlich mein ganzes Skript möglichst in unabhängige Einzelteile zerlegen muss, damit ich diese über ein Job-Array submitten kann und diese quasi gleichzeitig abgearbeitet werden und damit mehr Kerne nutzen?

Im Job-Skript muss ich dann wahrscheinlich irgendwo angeben, wann welche Python-Skripte laufen können. Wenn skript2.py die Ergebnisse von skript1.py benötigt, dann muss man da ja aufpassen.

Sehe ich das auch richtig, dass man in dieser Situation einfach viel mehr Ergebnisse speichern muss, da ja jetzt die einzelnen Berechnungen in unterschiedlichen Prozessen durchgeführt werden?

myScript1.py -> myScript1.out -> myScript3.py ->...
myScript2.py -> myScript2.out -> myScript4.py ->...



Wie oben erwähnt, lerne ich gerade Slurm erst kennen und ich bin ich gerade dabei mir zu überlegen, wie ich meinen Code umschreibe, um die CPUs/GPUs maximal gut zu nutzen und ich wollte nur wissen, ob das, wie ich mir das so vorstelle, überhaupt so ungefähr richtig ist. Es geht mir nur ums Big-Picture. Wie man das alles dann im Detail Slurm beibringt, das sollte ich selbst hinkriegen.
 
Zuletzt bearbeitet:
Ich habe noch nie Job Arrays bei Slurm genutzt. Klingt nach einem eher akademischen Feature.

Habe gerade nur ganz kurz in die Doku geschaut. Klingt eher nach einer Möglichkeit für Varianten-Rechnungen.

Also würde ich eher sagen, nein, Job-Arrays sind vermutlich nicht die richtige Art und Weise für dich, eine parallele Berechnung zu starten. Stattdessen musst du einen Job starten, der dann die Verteilung auf die dem Job zugewiesenen Kerne managt.
Zumal es eine übliche Clusterkonfiguration ist, nicht mehr als einen Job pro Knoten zu erlauben und das Job-Array dann Jobs auf verschiedenen Knoten starten könnte.

Parallele Programmierung kann übrigens alles andere als trivial sein. Hat Frust- und Spaßpotential.
Python und parallele Programmierung ist dann nochmal so eine Sache für sich...
Aber im einfachsten Fall verwendest du bspw. schlicht numpy Funktionen, die von Haus aus parallelisiert sind.

Bevor es also aufs Cluster geht, solltest du dich erstmal mit der Parallelisierung deines Codes an sich befassen.
 
  • Gefällt mir
Reaktionen: Yogi666, Peter_2498 und Micke
Peter_2498 schrieb:
und von einem wird auch erwartet, dass man die Ressourcen vom Cluster effizient nutzt, was ich absolut verstehen kann. Man will ja nicht, dass eine 96 Kerne CPU von einem Programm blockiert wird, welches 8 Kerne nutzt..
Kommt darauf an, wie du tasks oder cpus-per-task buchst.
Wenn du wie im einfachen Fall nur die Priorität buchst, behinderst du keine anderen Jobs, wenn deine Umgebung großzüger dimensioniert ist. Der Scheduler gibt ungenutzte Einheiten frei.

Peter_2498 schrieb:
Sehe ich das jetzt richtig, dass ich eigentlich mein ganzes Skript möglichst in unabhängige Einzelteile zerlegen muss, damit ich diese über ein Job-Array submitten kann und diese quasi gleichzeitig abgearbeitet werden und damit mehr Kerne nutzen?
Jenachdem was das Ziel ist. I.d.R. steht im Vordergrund, wie schnell man die Ergebnisse braucht. Wenn 1 Minute mehr oder weniger unbedeutend ist, darf man abwägen, ob 2 Tage länger am Skript zu feilen lohnt.
 
  • Gefällt mir
Reaktionen: Peter_2498
Peter_2498 schrieb:
Sehe ich das auch richtig, dass man in dieser Situation einfach viel mehr Ergebnisse speichern muss, da ja jetzt die einzelnen Berechnungen in unterschiedlichen Prozessen durchgeführt werden?

myScript1.py -> myScript1.out -> myScript3.py ->...
myScript2.py -> myScript2.out -> myScript4.py ->...
Nein, File I/O ist auf solchen Clustern ebenfalls nicht gerne gesehen, insbesondere, wenn du es von vielen Prozessen gleichzeitig tust.

Typischerweise parallelisiert man den Workload im Programm selbst. Bei C/C++ u.a. mit OpenMP oder MPI. Bei Python sollte man multiprocessing benutzen oder z.B. Python-MPI-Binding.
Du hast also normalerweise z.B. 96 Prozesse oder Threads, dasselbe die alle "myScript.py" ausführen und intern miteinander kommunizieren, um den Arbeit aufzuteilen.
 
  • Gefällt mir
Reaktionen: Yogi666 und Peter_2498
Micke schrieb:
Wenn du wie im einfachen Fall nur die Priorität buchst, behinderst du keine anderen Jobs, wenn deine Umgebung großzüger dimensioniert ist. Der Scheduler gibt ungenutzte Einheiten frei.
Ich weiß jetzt nicht ob ich dich richtig verstanden habe, aber bei uns auf dem Cluster ist das so gemacht, dass auf einem Knoten nur Jobs von einem User laufen dürfen und deswegen bezahlt man auch immer die Laufzeit so als ob man alle Kerne des jeweiligen Knotens nutzen würde. Deswegen wird bei Programmen empfohlen alle Kerne vom Knoten zu nutzen, also bei einem 96 Kerner , #SBATCH -c 96 einzutragen(weil man sie eh bezahlt) ODER man nutzt beispielsweise pro Job nur 24 Kerne und kann dann 4 Jobs gleichzeitig auf dem Knoten bearbeiten.

Bei uns sind die Knoten also immer für einen User reserviert.
 
Zuletzt bearbeitet:
Wenn es so konfiguriert ist, überschreibt das meine Antwort, stimmt.
Ich habe bei einer Uni eher eine geteilte Ressourcen Konfiguration erwartet, wo man für das von dir beschriebene Verhalten den Job mit --exclusive starten müsste. Weil es mehr neugierige Studenten als optimale Skripte geben dürfte.
 
@Micke An einer Uni könnte man sich eher vorstellen, dass ein Cluster(scheduler) für geteilte Resourcen konfiguriert ist, stimmt.
So wie ich es aus der Praxis (von verschiedenen Unternehmensclustern und aber auch vom HLRS (Uni Stuttgart), wenn man sich dort als Unternehmen Rechenleistung einkauft) kenne, werden aber üblicherweise schlicht Knoten gebucht.
Da braucht der User keinen RAM-Bedarf anzugeben, er muss halt stattdessen die passend bestückten Knoten wählen.
Und wenn man maximal einen Job pro Knoten erlaubt (soll heißen ein Job kann meherer Knoten verwenden, aber ich kann nicht mehrere Jobs gleichzeitig auf einen Knoten hauen), dann reduziert man damit auch die Wahrscheinlichkeit der Überbelegung*, sowohl was CPUs (bzw. Vektoreinheiten/FPUs) als auch RAM angeht.
Neuerdings wird ja eh alles auf GPU-Computing getrieben, da wird es ähnlich ein. Du willst eine GPU komplett für einen Job nutzen.

Lange Rede, kurzer Sinn: Die genauen Gegebenheiten hängen vom Einzelfall bzw. der konkreten Konfiguration ab.

Edit: *Es kommt in der Praxis schon mal vor, dass entweder Clustderscheduler falsch konfigureirt ist oder aber User Dinge falsch einstellen. Ich hab auch schon gesehen, dass Hyperthreading aktiviert war. Und wenn deine CPU reale 48 Kerne mit 48 FPUs hat, das Cluster aber mit Hyperthreading konfiguriert ist (ja, warum?) dann kann der Scheduler schonmal versuchen, da mehr als 48 Compute-Prozesse drauf zu schmeißen. Oder der User kann in seinem Skript angeben, dass er 20 Kerne möchte und dann trotzdem 30 Prozesse starten. Kann man zwar bestimmt irgendwie abfangen, ist aber zumindest zunächst alles andere als Ideal.
Wenn man sagt "hier hast du deinen Knoten exklusiv", dann ist das eben einfacher.
 
  • Gefällt mir
Reaktionen: Peter_2498 und Micke
Also ich habe jetzt schon ein wenig auf dem Cluster gearbeitet und aktuell passiert was, was ich nicht so recht verstehe und da es immer etwas dauert, bis mir der Support antwortet, wollte ich hier mal kurz fragen.

Ich habe ein Job-Array genutzt mit zwei Jobs die auf einem Knoten laufen sollten mit 96 Kernen und 4 GPUs.
Beide Jobs nutzen dabei jeweils 45 CPU-Kerne und eine GPU.

Was könnte es für Gründe geben, dass Slurm diese beiden Jobs nicht gleichzeitig abarbeitet sondern nacheinander? Wie oben schon geschrieben, sind bei uns die Knoten "user-exclusive" also hat man den Knoten für sich allein und da macht es natürlich gar kein Sinn, dass Slurm beide Jobs nacheinander abarbeitet, wenn er sie denn auch gleichzeitig abarbeiten könnte.

So sieht meine Config aus:

#!/bin/bash
#SBATCH -J meinJob
#SBATCH --mail-type=End
#SBATCH -a 1-2
#SBATCH -n 1
#SBATCH -c 45
#SBATCH --gres=gpu:t4
#SBATCH --mem-per-cpu=2G
#SBATCH -t 03:00:00
#SBATCH
# -------------------------------
module purge
module load cuda/12.5
module load intel/2025.0
module load python/3.13.1

source venv/bin/activate
python test${SLURM_ARRAY_TASK_ID}.py

EXITCODE=$?
exit $EXITCODE

Hab auch mal die Cores auf -c 20 reduziert und es passiert dasselbe.
Ergänzung ()

Hat sich erledigt. Wie ich gerade gesehen habe, sind GPU-Knoten bei uns nicht "user-exclusive" der Rest schon.
 
Zuletzt bearbeitet:
Zurück
Oben