# Exemple pour voir les GRES
sinfo -o "%10N %10P %20f" | grep gpu
scontrol show node io-gpu-01 | grep -i gres # Voir les types de GPU sur un nœud spécifique
Ce cours va maintenant vous aider à passer au niveau supérieur : utiliser le cluster de manière plus efficace, optimisée et autonome.
Pour utiliser efficacement un outil, il faut bien le connaître. C’est pareil pour un cluster !
Nœud(s) de Connexion (Login Node(s)) : Votre point d’entrée (ssh). Pour éditer, compiler, gérer vos fichiers, soumettre et suivre vos jobs. Pas pour les calculs intensifs !
Nœuds de Calcul (Compute Nodes) : Là où vos jobs s’exécutent réellement, alloués par SLURM. Vous n’y accédez généralement pas directement, sauf via SLURM (jobs batch ou interactifs).
Tous les nœuds ne sont pas identiques :
Nœuds CPU "Standard" : La majorité des nœuds, équipés de processeurs (CPU) avec un certain nombre de cœurs (192 cœurs) et une quantité standard de RAM (1500 Go). Ils sont polyvalents.
Nœuds GPU : Équipés de puissantes cartes graphiques (Graphics Processing Units). Indispensables pour l’Intelligence Artificielle (Deep Learning), certaines simulations (Dynamique Moléculaire…), le traitement d’images/vidéo.
Exemple sur ce cluster : Nous avons des nœuds avec des GPU Nvidia H100 (et d’autres avec des A100 mais réservés à certains utilisateurs).
Comment savoir ? La commande sinfo -o "%N %G" ou scontrol show node <nodename> peut montrer les Generic Resources (GRES) comme les GPU.
# Exemple pour voir les GRES
sinfo -o "%10N %10P %20f" | grep gpu
scontrol show node io-gpu-01 | grep -i gres # Voir les types de GPU sur un nœud spécifique
Nœuds "Grosse Mémoire" (bigmem) : Possèdent beaucoup plus de RAM que les nœuds standards (3 To). Utiles pour la génomique, les statistiques sur de très grands datasets, les bases de données en mémoire.
Comment vérifier sur ce cluster ?
# Afficher la mémoire par nœud (en Mo)
sinfo -N -o "%N %m" | sort -k2 -n -r | head # Affiche les nœuds avec le plus de mémoire
scontrol show node node-mem-01 | grep RealMemory # Mémoire totale sur un nœud spécifique
Les partitions sont des files d’attente logiques qui regroupent des nœuds et définissent des règles d’accès et des limites.
Association Nœuds/Partitions : Souvent, les nœuds spécifiques (GPU, bigMem) sont dans des partitions dédiées. Ex: defq (CPU std), gpu (nœuds GPU), bigmem.
Limites par Partition : Chaque partition a ses règles !
TimeLimit : Temps maximum autorisé pour un job. Crucial !
MaxNodes, MaxCPUsPerUser, etc. : Limites sur les ressources utilisables.
PriorityTier : Niveau de priorité de la partition.
Default=YES/NO : Est-ce la partition par défaut si vous n’en spécifiez pas ?
Explorer les partitions avec sinfo :
sinfo # Vue générale, peut être peu lisible sinfo -s # Résumé plus clair par partition (nœuds avail/idle/other/total) sinfo -p cpu # Détails sur la partition 'compute' (adapter le nom) sinfo -p gpu -l # Format long (-l) pour la partition 'gpu' (montre les limites) # Exemple de sortie pour sinfo -p compute -l (tronqué) : # PARTITION AVAIL TIMELIMIT NODES STATE NODELIST # cpu* up 7-00:00:00 10 idle node[001-010] # cpu* up 7-00:00:00 5 alloc node[011-015] # -> * indique partition par défaut, TIMELIMIT est 7 jours, 10 noeuds idle, 5 alloués.
Au-delà des limites de partitions, le cluster a des règles globales :
Quotas Disque : Votre espace $HOME est limité (xxxx 50 Go), le scratch est plus plus grand (plus de 1Po) mais il est temporaire et partagé entre tous les utlisateurs. Utilisez quota -s (si disponible) ou une commande locale pour vérifier.
# Exemple (si la commande quota est configurée) quota -s # Filesystem space quota limit grace files quota limit grace # /dev/sda1... 40G 45G 50G 100k 180k 200k
Limite de Jobs : Vous ne pouvez peut-être pas lancer plus de Xxxxx jobs (ex: xxxxx1000 jobs au total, xxxxxx200 jobs RUNNING simultanément).
Fair-share : SLURM utilise sur ce cluster un système de priorité dynamique ("fair-share") qui favorise les utilisateurs/groupes ayant peu utilisé le cluster récemment. Votre priorité influence le temps d’attente. Utilisez sshare -U -l pour voir votre "part" (si autorisé).
Demander "juste ce qu’il faut" est la clé pour ne pas gaspiller, réduire l’attente et éviter les erreurs.
Gaspillage : Demander 1 To de RAM si votre job n’en utilise que 10 Go bloque ce To inutilement pour les autres.
Temps d’Attente : Un job demandant peu de ressources (1 coeur, peu de temps) trouvera plus facilement une place qu’un job énorme.
Plantages : Si vous sous-estimez la mémoire ou le temps, SLURM tuera votre job !
Lire la Doc du Logiciel : Souvent, la documentation de votre code scientifique donne des pistes : "Requires ~4GB RAM per core for typical datasets."
Commencer Petit & Observer :
Scénario : Vous devez traiter 1000 fichiers.
Test : Lancez votre script sur 1 seul fichier avec des ressources modestes mais suffisantes pour un fichier (à adapter selon votre account-et-qos) :
# Script test_job.sh #SBATCH --job-name=TestRun #SBATCH --output=test_out_%j.out #SBATCH --error=test_err_%j.err #SBATCH --time=00:30:00 # 30 minutes pour un fichier ? #SBATCH --mem=2G # 2 Go pour un fichier ? #SBATCH --cpus-per-task=1 #SBATCH --nodes=1 #SBATCH --ntasks=1 #SBATCH --partition=debug # Partition de test ./mon_programme --input fichier_test.dat --output resultat_test.res
Analyse : Une fois le job terminé (ID 12345), utilisez sacct :
sacct -j 12345 -o jobid,jobname,state,elapsed,reqmem,maxrss,exitcode # Output exemple : # JobID JobName State Elapsed ReqMem MaxRSS ExitCode # ------------ ---------- ---------- ---------- -------- ---------- -------- # 12345 TestRun COMPLETED 00:10:15 2000M 1530M 0:0
Interprétation : Le job a pris ~10 min (bien moins que 30 min) et a utilisé ~1.5 Go de RAM (MaxRSS, bien moins que 2 Go).
Extrapolation prudente : Pour 1000 fichiers (peut-être avec un Job Array, voir section 4), vous pourriez demander --time=00:15:00 par tâche (10 min + marge) et --mem=2G (1.5 Go + marge).
Tests de "Scaling" (pour code parallèle) :
Objectif : Voir si utiliser 2x plus de cœurs divise le temps par 2.
Méthode : Lancez le même calcul (sur un jeu de données de taille fixe) avec --cpus-per-task=1, puis =2, =4, =8, =16, etc. (pour OpenMP) ou avec --ntasks=1, 2, 4, 8, 16… (pour MPI sur 1 nœud). Notez le temps Elapsed via sacct pour chaque run.
Analyse : Faites un graphique Temps vs. Nombre de cœurs/tâches. Si la courbe s’aplatit vite (ex: passer de 8 à 16 cœurs ne fait gagner que 10%), demander plus de 8 cœurs est inefficace.
Soyez précis dans vos directives #SBATCH.
CPU : Le trio --nodes, --ntasks et --cpus-per-task
Cas Séquentiel (1 processus, 1 cœur) : Le plus simple.
#SBATCH --nodes=1 # Un seul noeud #SBATCH --ntasks=1 # Une seule tâche (processus) #SBATCH --cpus-per-task=1 # Un seul coeur pour cette tâche
Cas OpenMP (Multithreading sur 1 nœud) : Un processus utilisant plusieurs cœurs via des threads.
#SBATCH --nodes=1 # Un seul noeud #SBATCH --ntasks=1 # Une seule tâche (processus) #SBATCH --cpus-per-task=16 # Demande 16 coeurs pour ce processus # Important : Informer OpenMP du nombre de threads alloués export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK echo "Lancement OpenMP avec $OMP_NUM_THREADS threads." ./mon_executable_openmp
Cas MPI (Plusieurs processus, potentiellement sur plusieurs nœuds) :
#SBATCH --nodes=4 # Demande 4 noeuds #SBATCH --ntasks-per-node=32 # Lance 32 processus MPI sur chaque noeud # Total ntasks = 4 * 32 = 128 #SBATCH --cpus-per-task=1 # Chaque processus MPI tourne sur 1 coeur module load openmpi/XYZ # Charger la bonne librairie MPI echo "Lancement MPI sur $SLURM_NNODES noeuds, $SLURM_NTASKS tâches." # srun gère la distribution des tâches sur les noeuds alloués srun ./mon_executable_mpi
_ On peut aussi utiliser --ntasks=128 et laisser SLURM répartir, mais --ntasks-per-node est souvent plus explicite.
|
Mémoire : Totale ou par CPU ?
--mem=<quantité> : Mémoire totale pour le job. Simple si vous connaissez le besoin global.
#SBATCH --mem=64G # Demande 64 Gigaoctets au total pour le job
--mem-per-cpu=<quantité> : Mémoire par cœur CPU demandé. Utile si la consommation mémoire dépend du nombre de cœurs.
# Demande 16 coeurs (cpus-per-task=16) et 4Go par coeur # Mémoire totale = 16 * 4Go = 64Go #SBATCH --cpus-per-task=16 #SBATCH --mem-per-cpu=4G
Attention aux unités : M ou MB pour Mégaoctets, G ou GB pour Gigaoctets. 1G != 1000M (c’est 1024M).
Toujours ajouter une marge, mais pas trop ! Si sacct montre MaxRSS=10G, demandez --mem=12G ou 13G.
Temps : --time=<HH:MM:SS>
Format Jours-HH:MM:SS possible aussi (ex: --time=2-00:00:00 pour 2 jours).
Si votre job finit en 5h, demander 24h peut le faire attendre plus longtemps car il bloque un slot plus grand.
Si votre job finit en 5h, demander 5h05 est risqué. Mieux vaut 6:00:00 ou 7:00:00.
Exemple :
#SBATCH --time=06:00:00 # Demande 6 heures
Partition : --partition=<nom_partition>
Obligatoire si vous avez besoin de ressources spécifiques (GPU, HighMem).
Utile pour choisir des limites adaptées
GPU : --gres=gpu:<type>:<nombre>
La syntaxe exacte (--gres ou autre) et les types de GPU (a100, h100, …) dépendent de la configuration locale.
Exemple pour demander 2 GPU H100 :
#SBATCH --gres=<type>:<profil>:<quantité> #SBATCH --partition=gpu-dedicated # Assurez-vous d'être sur la bonne partition
Exemple pour demander 1 GPU quelconque :
#SBATCH --gres=gpu:1 #SBATCH --partition=gpu-dedicated
Pour soumettre sur un noued GPU, on pourra utiliser, par exemple, la commande suivante :
sbatch -A projA -p gpu --gres=gpu:nvidia_h100_80gb_hbm3:2 --time=04:00:00 script_gpu.sh
Vous trouverez ci-dessous des informations pour trouver les profils (Gres) utilisés :
# Je suis sur du dédié
dedicated_gpu_nodes=$(scontrol show partition gpu-dedicated |awk -F"=" '{if (($1 ~ "Nodes") && ($2 ~ "gpu")) {print $2}}')
# liste des nœuds GPU
echo $dedicated_gpu_nodes
# liste de mes Gres auxquelles j'ai accès
scontrol show nodes $dedicated_gpu_nodes |awk -F"=" '{if ($1 ~ "Gres") {print $2}}' |awk -F"[:()]" 'BEGIN {RS = ","} {print $1":"$2}'
Sur du calcul à la consommation en CPU/h, on remplacera "dedicated" par "ondemand" ci-dessus, mais les profils disponibles sont les mêmes pour l’instant (en date du 12/09/2025).
Sur le cluster IO les profils GPU (Gres) sont les suivants :
scontrol show node io-gpu-01 |grep Gres
Gres=gpu:nvidia_h100_80gb_hbm3:2(S:0),gpu:nvidia_h100_80gb_hbm3_4g.40gb:2(S:0),gpu:nvidia_h100_80gb_hbm3_1g.10gb:6(S:0)
Ce qui, par exemple, pourrait transformer le job de soumission ainsi :
#SBATCH --gres=gpu:nvidia_h100_80gb_hbm3:1 # pour une carte H100 entière. #SBATCH --partition=gpu-dedicated
| Pensez (aux autres !) à prendre un profil de carte plus petit si ça rentre dans 10G ou 40G de mémoire ! |
Explorons plus en détail les commandes que vous connaissez et découvrons-en d’autres.
sbatch <script.sh> : Le Standard
Options avancées utiles dans le script ou en ligne de commande :
# Dans le script : #SBATCH --dependency=afterok:12345 # Dépendance (voir section 4) #SBATCH --array=1-50 # Job Array (voir section 4) #SBATCH --mail-type=END,FAIL # Notification email fin et erreur #SBATCH --mail-user=[adresse e-mail supprimée] # En ligne de commande (override le script) : sbatch --time=01:00:00 --mem=2G mon_script_habituel.sh
salloc [options_ressources] : Allocation Interactive
Réserve les ressources maintenant et vous donne un shell sur le premier nœud alloué. Vous restez dedans jusqu’à ce que vous fassiez exit ou que le temps soit écoulé.
Exemple : Réserver 1 nœud avec 4 cœurs et 8Go pour 2 heures.
salloc --nodes=1 --ntasks=1 --cpus-per-task=4 --mem=8G --time=02:00:00 # Vous obtenez un prompt, mais vous êtes maintenant sur un noeud de calcul ! # Exemple : [votre_login@node007 ~]$ # Vous pouvez maintenant lancer des commandes, compiler, exécuter... ./mon_programme -i data.txt # ... puis faire 'exit' quand vous avez fini. exit
Utile pour : débogage long, compilation nécessitant des ressources spécifiques, lancer plusieurs srun manuellement.
srun [options_ressources] <commande> : Lancement Direct
Peut être utilisé de deux manières principales :
Hors allocation (sbatch/salloc) : Alloue les ressources et lance la commande immédiatement en avant-plan (foreground). Bloque votre terminal jusqu’à la fin.
# Lancer 'hostname' sur un noeud de la partition debug srun --partition=debug --nodes=1 --ntasks=1 hostname # Output : node008 # Lancer un shell interactif court (équivalent à salloc + shell) srun --partition=debug --mem=1G --time=0:15:00 --pty bash -l # [votre_login@node009 ~]$ exit
Le --pty est nécessaire pour obtenir un terminal interactif correct.
Dans une allocation (sbatch/salloc) : Lance une tâche (souvent parallèle MPI) en utilisant les ressources déjà allouées. C’est la méthode standard pour lancer des applications MPI.
# Extrait d'un script sbatch ayant demandé --nodes=2 --ntasks=64 module load openmpi/XYZ srun ./mon_executable_mpi # srun lance 64 processus répartis
squeue : état des jobs demandés
Options de filtrage et formatage :
squeue -u $USER # Vos jobs squeue -p gpu # Jobs sur la partition gpu squeue -j 12345,12346 # Voir ces deux jobs spécifiques squeue -t RUNNING -u $USER # Vos jobs en cours d'exécution squeue -u $USER --start # Voir l'heure de début estimée (si disponible) ! Utile pour les jobs PD. # Format personnalisé (très utile !) # Affiche ID, Partition, Nom, Utilisateur, Etat, Temps utilisé, Noeuds squeue -u $USER -o "%.10i %.10P %.20j %.10u %.5T %.12M %.20N" # Ou avec des noms de champs plus longs (voir 'man squeue' pour la liste) squeue -u $USER --Format=JobID:10,Partition:10,Name:25,State:5,TimeUsed:12,NodeList:35
scancel <job_id> : Annuler un job
scancel 12345 : Annule le job 12345.
scancel 12345 12346 : Annule plusieurs jobs.
scancel -u $USER -t PENDING : Annule tous VOS jobs en attente.
scancel -u $USER -n MonJobSpecial : Annule vos jobs ayant ce nom.
scancel --state=PENDING --partition=long : Annule tous les jobs en attente sur la partition 'long' (nécessite souvent des droits admin).
scontrol : L’Outil de l’Expert
Permet de voir énormément de détails et parfois de modifier des jobs.
Voir les détails d’un job :
scontrol show job 12345 # Cherchez les lignes : JobState, RunTime, TimeLimit, NodeList, NumNodes, NumCPUs, CpusPerTask, ReqMem, MemPerNode, Gres, WorkDir...
Voir les détails d’un nœud :
scontrol show node node001 # Cherchez : State (idle, alloc, down...), CPUTot, CPUAlloc, CPULoad, RealMemory, AllocMem, FreeMem, Gres, Partitions...
Modifier un job (si autorisé xxxxxx ) :
# Augmenter la limite de temps d'un job EN COURS (RUNNING) à 3h scontrol update JobId=12345 TimeLimit=03:00:00 # Changer la partition d'un job EN ATTENTE (PENDING) scontrol update JobId=54321 Partition=long # Ajouter un commentaire scontrol update JobId=12345 Comment="Augmentation temps suite à test"
sinfo : L’État du Cluster
sinfo -s : Résumé par partition (souvent le plus utile).
sinfo -N -l : État détaillé de chaque nœud (long).
sinfo -p gpu --Format=NodeList:20,CPUsState:15,Memory:10,Gres:30 : Format personnalisé pour voir les CPU (Alloc/Idle/Other/Total), la mémoire et les GRES des nœuds de la partition GPU.
sacct : La Mémoire du Cluster (Jobs Terminés)
Indispensable pour analyser la consommation réelle !
Voir un job spécifique :
sacct -j 12345 # Affichage par défaut, peut inclure plusieurs lignes (job principal, batch step, extern step)
Format personnalisé et utile :
sacct -j 12345 -o jobid,jobname,partition,alloccpus,state,exitcode,elapsed,timelimit,reqmem,maxrss,nodelist # JobID JobName Partition AllocCPUS State ExitCode Elapsed TimeLimit ReqMem MaxRSS NodeList # ------------ ---------- ---------- ---------- ---------- -------- ---------- ---------- ---------- ---------- --------------- # 12345 MonJob compute 8 COMPLETED 0:0 00:55:10 01:00:00 16G 14854M node[001-002]
Interprétation : Job 12345 nommé "MonJob" sur partition "compute", a utilisé 8 CPUs, terminé avec succès (COMPLETED, ExitCode 0:0), a duré 55m10s (pour 1h demandée), a demandé 16G de RAM, mais n’en a utilisé au maximum que ~14.8G (MaxRSS), sur les nœuds node001 et node002. → On pourrait réduire la RAM demandée !
Filtrer par date, état, utilisateur :
# Mes jobs depuis hier sacct -u $USER -S yesterday # Mes jobs qui ont échoué (Failed ou Timeout) aujourd'hui sacct -u $USER -S today -E now --state=F,TO
Note : sacct peut prendre du temps s’il y a beaucoup de jobs dans la base de données. Utilisez des filtres !
Pourquoi ? Débogage pas-à-pas (avec gdb), compilation longue ou nécessitant des libs spécifiques, tests rapides avant de lancer un gros batch, logiciels graphiques.
Comment ?
srun --pty … bash -l : Simple et direct.
# Demander 1h sur 1 noeud avec 4 coeurs et 8Go RAM srun --time=01:00:00 --nodes=1 --cpus-per-task=4 --mem=8G --pty bash -l # Vous êtes sur un noeud de calcul. Compilez, lancez gdb, etc. # [user@node003 ~]$ gcc -fopenmp my_code.c -o my_exec # [user@node003 ~]$ gdb ./my_exec # ... (gdb session) ... # [user@node003 ~]$ exit # Libère l'allocation
salloc … : Pour des sessions plus longues ou pour lancer plusieurs srun depuis l’allocation.
salloc --time=04:00:00 --nodes=2 --ntasks-per-node=4 --mem=16G # Allocation 12346 accordée. Vous avez un shell sur le premier noeud. # [user@node005 ~]$ module load intelmpi # [user@node005 ~]$ srun -N 2 -n 8 ./mon_mpi_app # Lance sur les 2 noeuds alloués # ... attendre la fin ... # [user@node005 ~]$ exit # Libère l'allocation 12346
Applications Graphiques (avec X11 forwarding) :
Connectez-vous au cluster avec ssh -X votre_login@cluster (ou -Y).
Demandez une allocation interactive avec srun --x11 … :
srun --x11 --time=01:00:00 --mem=8G --cpus-per-task=2 --pty bash -l # Une fois sur le noeud de calcul: module load paraview # Charger le logiciel graphique paraview & # Lancer l'application. La fenêtre devrait s'ouvrir sur VOTRE écran.
| Le X11 forwarding peut être lent ou inutilisable selon le réseau entre le cluster et votre position. |
Principe : Lancer le même script N fois, chaque instance ayant un indice unique $SLURM_ARRAY_TASK_ID. Idéal pour : traiter une série de fichiers, tester différentes valeurs d’un paramètre.
Syntaxe sbatch --array=<indices>%<limite> :
--array=1-100 : Lance 100 tâches, numérotées de 1 à 100.
--array=0-49 : Lance 50 tâches, numérotées de 0 à 49.
--array=1,5,10-15 : Lance les tâches 1, 5, 10, 11, 12, 13, 14, 15.
--array=1-100%10 : Lance 100 tâches, mais pas plus de 10 en même temps. Très utile pour ne pas saturer le cluster ou les licences.
Utilisation dans le script : La variable $SLURM_ARRAY_TASK_ID contient l’indice de la tâche courante.
Exemple concret : Traiter 50 fichiers nommés data_00.csv à data_49.csv.
#!/bin/bash
#SBATCH --job-name=ArrayProcess
#SBATCH --output=array_out_%A_%a.out # %A = ID du job Array global, %a = ID de la tâche
#SBATCH --error=array_err_%A_%a.err
#SBATCH --time=00:15:00 # Temps par tâche
#SBATCH --mem=1G # Mémoire par tâche
#SBATCH --cpus-per-task=1
#SBATCH --array=0-49%20 # Lance 50 tâches (0-49), 20 simultanément max
echo "Début tâche Array $SLURM_ARRAY_TASK_ID du job $SLURM_ARRAY_JOB_ID"
echo "Noeud: $(hostname)"
# Formatage de l'indice avec des zéros devant (ex: 00, 01, ..., 49)
TASK_ID_FORMATTED=$(printf "%02d" $SLURM_ARRAY_TASK_ID)
INPUT_FILE="data_${TASK_ID_FORMATTED}.csv"
OUTPUT_FILE="result_${TASK_ID_FORMATTED}.txt"
echo "Traitement de $INPUT_FILE -> $OUTPUT_FILE"
# Vérifier si le fichier existe avant de le traiter
if [ -f "$INPUT_FILE" ]; then
./mon_analyse --input $INPUT_FILE --output $OUTPUT_FILE
echo "Tâche $SLURM_ARRAY_TASK_ID: Succès"
else
echo "Tâche $SLURM_ARRAY_TASK_ID: Erreur, fichier $INPUT_FILE non trouvé"
exit 1 # Important de sortir en erreur si besoin
fi
echo "Fin tâche Array $SLURM_ARRAY_TASK_ID"
Gestion : squeue montre le job array global (ex: 12345_[1-50]) et les tâches individuelles (ex: 12345_1, 12345_2…). scancel 12345 annule tout l’array. scancel 12345_3 annule seulement la tâche 3.
Principe : Conditionner le démarrage d’un job à l’état de fin d’un ou plusieurs autres jobs.
Syntaxe sbatch --dependency=<type>:<job_id_list> … :
<job_id_list> peut être un seul ID (12345) ou plusieurs séparés par des deux-points (12345:12346).
<type> définit la condition :
afterok : Démarre seulement si tous les jobs listés se terminent avec succès (ExitCode 0). Le plus courant.
afterany : Démarre dès que les jobs listés sont terminés, peu importe leur état (succès, erreur, annulé).
afternotok : Démarre seulement si au moins un des jobs listés se termine en erreur. Utile pour lancer un nettoyage ou une notification.
singleton : Démarre seulement si aucun autre job avec le même nom et le même utilisateur n’est en cours d’exécution. Utile pour des tâches périodiques uniques.
Exemple de Workflow (Simulation → Analyse → Visualisation) :
# 1. Soumettre la simulation sbatch script_simulation.sh # Admettons que SLURM retourne "Submitted batch job 5001" # 2. Soumettre l'analyse, qui dépend du succès de la simulation sbatch --dependency=afterok:5001 script_analyse.sh # Admettons que SLURM retourne "Submitted batch job 5002" # 3. Soumettre la visualisation, qui dépend du succès de l'analyse sbatch --dependency=afterok:5002 script_visualisation.sh # Admettons que SLURM retourne "Submitted batch job 5003" # 4. (Optionnel) Soumettre une notification si la simulation échoue sbatch --dependency=afternotok:5001 script_notif_erreur.sh
Voir les dépendances : scontrol show job <job_id> (ligne Dependency=…) ou squeue -o "%.10i %.20j %.15E" (colonne DEPENDENCY).
OpenMP (Mémoire Partagée, 1 Nœud) : Threads sur un seul nœud.
Script Exemple : (Identique à la section 2.3)
#!/bin/bash #SBATCH --job-name=OpenMP_Job #SBATCH --nodes=1 --ntasks=1 --cpus-per-task=16 # 16 threads #SBATCH --mem=4G --time=1:00:00 export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK echo "Lancement avec $OMP_NUM_THREADS threads OpenMP sur $(hostname)" ./mon_executable_openmp
MPI (Message Passing, >=1 Nœud) : Processus communiquant via le réseau.
Script Exemple : (Identique à la section 2.3)
#!/bin/bash #SBATCH --job-name=MPI_Job #SBATCH --nodes=4 --ntasks-per-node=32 # 128 processus au total #SBATCH --mem=0 # Toute la mémoire du noeud par processus #SBATCH --time=2:00:00 module load xxxxintelmpi/XYZ # Charger MPI echo "Lancement MPI ($SLURM_NTASKS tâches) sur $SLURM_NNODES noeuds" srun ./mon_executable_mpi # srun lance et gère les processus MPI
Important : srun est souvent la méthode préférée (et parfois la seule supportée) pour lancer des exécutables MPI sous SLURM car il s’intègre bien avec l’allocation des ressources. Évitez mpirun ou mpiexec xxxxxx sauf si la documentation locale le recommande explicitement.
Hybride (MPI + OpenMP) : Chaque processus MPI utilise plusieurs threads OpenMP.
Script Exemple : 4 processus MPI, chacun utilisant 8 threads OpenMP.
#!/bin/bash #SBATCH --job-name=Hybrid_Job #SBATCH --nodes=1 # Un seul noeud dans cet exemple #SBATCH --ntasks=4 # 4 processus MPI #SBATCH --cpus-per-task=8 # 8 coeurs (threads OpenMP) par processus MPI #SBATCH --mem=32G #SBATCH --time=1:30:00 export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK module load xxxxxintelmpi/XYZ # Charger MPI echo "Lancement Hybride: $SLURM_NTASKS tâches MPI, $OMP_NUM_THREADS threads/tâche" srun ./mon_executable_hybride
Demande de Ressource Clé : --gres=gpu:<type>:<nombre>.
Modules Essentiels : Souvent cuda et/ou cudnn.
Exemple Concret (PyTorch sur 1 GPU H100) :
#!/bin/bash #SBATCH --job-name=Pytorch_H100 #SBATCH --output=pytorch_h100_%j.out #SBATCH --error=pytorch_h100_%j.err #SBATCH --time=04:00:00 # Temps pour l'entraînement #SBATCH --nodes=1 # Généralement 1 noeud pour commencer #SBATCH --ntasks=1 #SBATCH --cpus-per-task=8 # Donner assez de CPU pour pré-traitement/data loading #SBATCH --mem=64G # La RAM CPU est aussi importante #SBATCH --partition=gpu # ADAPTER la partition ! #SBATCH --gres=gpu:h100:1 # Demande 1 GPU H100 (ADAPTER type/syntaxe !) echo "Début Job PyTorch sur $(hostname)" echo "GPU alloué(s) : $CUDA_VISIBLE_DEVICES" # Vérification # Charger les modules (exemple) module purge module load xxxxxcuda/12.x # ADAPTER la version CUDA module load python/3.10 module load pytorch/XYZ # Charger le module Pytorch précompilé si disponible # Activer un environnement virtuel si nécessaire # source /path/to/my_venv/bin/activate # Lancer nvidia-smi pour vérifier que le GPU est vu (optionnel) nvidia-smi echo "Lancement du script Python..." # Lancer le script d'entraînement python train_model.py --data /path/to/data --epochs 50 --batch_size 64 echo "Fin du Job PyTorch."
Points Clés :
Demander assez de cpus-per-task et mem (CPU) pour que le GPU ne soit pas bridé par la préparation des données.
Vérifier la syntaxe exacte de --gres et les noms des partitions/types de GPU sur votre cluster.
Charger les bons modules cuda.
Un job qui tourne, c’est bien. Un job qui tourne bien, c’est mieux !
Utile pour voir si le job se comporte comme prévu (utilise le CPU, la RAM, le GPU…).
Méthode 1 : Connexion au nœud (si autorisé)
Trouver le nœud : squeue -j <job_id> -o "%N"
Se connecter : ssh <nom_du_noeud> (peut être désactivé par sécurité).
Utiliser les outils :
top ou htop : Voir l’utilisation CPU et mémoire des processus.
nvidia-smi : Voir l’utilisation du GPU (charge %, mémoire utilisée %).
iotop (si installé) : Voir les entrées/sorties disque.
Méthode 2 : srun dans le job
Moins direct, mais parfois la seule option.
Lancez une commande de monitoring via srun à l’intérieur de votre allocation (surtout utile dans salloc ou si vous vous connectez via srun --jobid …).
# Dans une session salloc ou via srun --jobid=... --pty bash srun --nodes=1 --ntasks=1 top -b -n 1 # Lance top en mode batch 1 fois srun --nodes=1 --ntasks=1 nvidia-smi # Lance nvidia-smi
sacct et seffsacct : Votre meilleur ami pour l’optimisation !
Rappel de la commande utile :
sacct -j <job_id> -o jobid,jobname,state,elapsed,timelimit,reqmem,maxrss,reqcpus,alloccpus,exitcode
Focus sur :
MaxRSS vs ReqMem : Efficacité mémoire. Si MaxRSS << ReqMem, réduisez ReqMem.
Elapsed vs TimeLimit : Efficacité temps. Si Elapsed << TimeLimit, réduisez TimeLimit.
AllocCPUS vs utilisation réelle (difficile à voir directement avec sacct, mais seff aide) : Efficacité CPU.
ExitCode : 0:0 = OK. Autre chose = Erreur (voir Section 6).
seff <job_id> : Le Rapport d’Efficacité (si disponible)
Fournit un résumé très pratique.
Exemple de sortie seff 12345 :
Job ID: 12345 Cluster: my_cluster User/Group: user/group State: COMPLETED (exit code 0) Nodes: 1 Cores per node: 8 CPU Utilized: 01:15:30 (Wall Time: 00:10:05) # Temps CPU total vs Temps réel CPU Efficiency: 93.80% of 8 core-walltime # Bon ! Job Wall-clock time: 00:10:05 Memory Utilized: 5.50 GB Memory Efficiency: 68.75% of 8.00 GB # Pourrait être mieux
Très utile pour voir rapidement l’efficacité CPU et Mémoire.
SLURM vous donne les ressources, mais votre code les utilise-t-il bien ?
Profiling Simple : Utilisez la commande time devant les étapes clés de votre script SLURM.
echo "Début préparation données : $(date)" time ./prepare_data.sh echo "Fin préparation données : $(date)" echo "Début calcul principal : $(date)" time srun ./mon_executable_mpi echo "Fin calcul principal : $(date)"
Regardez le temps "real", "user", "sys" dans la sortie .out.
Outils de Profiling Dédiés : Si disponibles xxxxxx (module avail …)
gprof : Simple, pour code C/C++/Fortran compilé avec -pg.
Intel VTune Profiler : Très puissant pour code C/C++/Fortran, MPI, OpenMP sur CPU Intel.
Nvidia Nsight Systems / Compute : Indispensables pour analyser les performances du code CUDA sur GPU Nvidia.
Analyse I/O :
Vos calculs sont rapides mais le job est lent ? Peut-être à cause des lectures/écritures disque (I/O).
Utilisez strace -c -p <PID> (avancé !) sur un processus pour voir le temps passé dans les appels système liés aux I/O.
Règle d’or : Travaillez sur les systèmes de fichiers scratch (plus rapides) pour les données volumineuses et temporaires. Évitez de lire/écrire des Go de données depuis/vers votre $HOME.
Utilisez les informations de sacct, seff, et de vos analyses pour ajuster vos prochaines soumissions.
"Right-sizing" (Ajustement précis) :
Si seff montre 90% CPU Eff. et 50% Mem Eff. pour --mem=20G, essayez --mem=12G la prochaine fois (10G utilisé + 20% marge).
Si Elapsed était 3h et TimeLimit 10h, essayez --time=4:00:00.
Choix de Partition : Si votre job de test prend 15 min sur defq, utilisez la partition debug (xxxxx) pour les prochains tests rapides. Si votre job prend 3 jours, assurez-vous que la partition defq le permet. Les limites des partitions peuvent évoluer dans le temps.
Stratégie I/O dans le script :
#!/bin/bash
# ... directives SBATCH ...
# Créer un répertoire de travail temporaire sur scratch
SCRATCH_DIR="xxxxx/scratch/$USER/job_${SLURM_JOB_ID}"
mkdir -p $SCRATCH_DIR
cd $SCRATCH_DIR
# Copier les données d'entrée depuis $HOME (ou autre stockage lent)
echo "Copie des données d'entrée..."
cp $SLURM_SUBMIT_DIR/input_data.dat .
# Lancer le calcul qui lit/écrit dans le répertoire courant ($SCRATCH_DIR)
echo "Lancement du calcul..."
./mon_executable --input input_data.dat --output results.tmp
# Copier les résultats importants vers le répertoire de soumission
echo "Copie des résultats..."
cp results.tmp $SLURM_SUBMIT_DIR/final_results_${SLURM_JOB_ID}.txt
# Nettoyer le répertoire scratch (IMPORTANT !)
echo "Nettoyage..."
cd $SLURM_SUBMIT_DIR # Revenir avant de supprimer
rm -rf $SCRATCH_DIR
echo "Job terminé."
Job Arrays vs Boucle for : Si vous avez 1000 tâches indépendantes, un Job Array (--array=1-1000) est beaucoup plus efficace (gestion par SLURM, parallélisation facile) qu’une boucle for i in {1..1000}; do sbatch …; done dans un script.
Parallélisme : Ne demandez pas 128 cœurs si vos tests de scaling montrent que le gain est minime après 32.
Même avec une bonne préparation, les problèmes arrivent. Voici comment les aborder.
PD - Pending)Voir la raison :
squeue -j <job_id> -o "%.10i %.10u %.5T %.15E" # La colonne REASON est la clé # Exemples de raisons : # (Resources) : Pas assez de noeuds/CPU/mem/GPU libres actuellement. Patientez ! # (Priority) : D'autres jobs sont prioritaires (fair-share). Patientez ! # (Dependency) : Attend la fin d'un autre job. Vérifiez le job parent. # (PartitionTimeLimit) : Le temps demandé dépasse la limite de la partition. Réduisez --time ou changez de partition. # (QOSMaxCpuPerUser) : Vous avez atteint votre limite de CPUs alloués en même temps. Attendez que d'autres jobs finissent. # (AssocGrpGRES) : Vous avez atteint votre limite de GPUs pour votre groupe. # (ReqNodeNotAvail) : Un nœud spécifique demandé n'est pas disponible (down, reserved...).
Actions possibles : Être patient, vérifier si la demande est réaliste pour la partition (sinfo -p …), annuler (scancel) et resoumettre avec moins de ressources ou sur une autre partition.
F - Failed, TO - Timeout, OOM - Out Of Memory)REGARDER LE FICHIER .err DU JOB ! C’est la première source d’indices.
Utiliser sacct -j <job_id> -o …** pour voir ExitCode, State, MaxRSS.
State=OUT_OF_MEMORY ou OOM / Erreur "Killed" dans .err / MaxRSS proche ou > ReqMem : Manque de mémoire. Augmentez --mem ou --mem-per-cpu.
# Job 12345 a échoué par manque de mémoire (demandé 4G, utilisé plus) sacct -j 12345 -o jobid,reqmem,maxrss,state # Output: 12345 4000M 4150M OUT_OF_MEMORY # Solution: Relancer avec --mem=6G (ou plus)
State=TIMEOUT / Erreur "CANCELLED due to time limit" dans .err : Temps écoulé. Augmentez --time.
sacct -j 12346 -o jobid,elapsed,timelimit,state # Output: 12346 01:00:00 01:00:00 TIMEOUT # Solution: Relancer avec --time=01:30:00 (ou plus)
State=FAILED, ExitCode != 0:0 / Erreur applicative dans .err (ex: "Segmentation fault", "Error in calculation") : Problème dans votre code ou son utilisation.
Lire attentivement le message d’erreur dans le .err.
Vérifier les paramètres d’entrée du programme.
Essayer de reproduire l’erreur sur un petit cas en job interactif (srun --pty) pour utiliser un débogueur (gdb).
Erreur "No such file or directory" dans .err :
Vérifiez les chemins d’accès dans votre script. Utilisez des chemins absolus si besoin.
Assurez-vous que le fichier existe avant le lancement (if [ -f … ]).
Vérifiez les permissions en lecture (et écriture) (ls -l).
Assurez-vous que le fichier est accessible depuis les nœuds de calcul (sur le stockage partagé).
Erreur "command not found" dans .err :
Avez-vous chargé le bon module (module load …) ?
Le chemin vers l’exécutable est-il correct ? Est-il dans le $PATH ?
Erreur de bibliothèque (cannot open shared object file: No such file or directory) :
Module manquant ou incorrect ? (module load …).
Problème de LD_LIBRARY_PATH ? (Moins courant avec les modules).
Vérifier l’efficacité (seff <jobid>) :
Faible CPU Efficiency : Le code attend beaucoup (I/O ?), ou vous avez demandé trop de cœurs pour un code peu parallèle.
Faible Memory Efficiency : Vous avez demandé beaucoup trop de RAM. Réduisez la demande.
Identifier le goulot d’étranglement :
I/O ? Chronométrez les étapes de lecture/écriture (time …), utilisez strace (avancé), travaillez sur scratch.
CPU ? Le code est-il bien parallélisé (OpenMP/MPI) ? Les cœurs sont-ils tous utilisés (top/htop) ? Utilisez un profiler.
Réseau (MPI) ? La communication entre processus est-elle trop importante ? Le réseau est-il saturé ? (Plus difficile à diagnostiquer).
Tester différentes configurations : Variez le nombre de cœurs/nœuds, les paramètres du programme, la taille des données pour comprendre où le temps est passé.
Vous avez maintenant les clés pour utiliser SLURM de manière plus réfléchie et efficace.
Les Points Clés à Retenir :
Connaissez votre cluster : Matériel, partitions, politiques.
Estimez vos besoins : Ni trop, ni trop peu. Commencez petit, observez (sacct, seff), ajustez.
Maîtrisez les commandes : sbatch, squeue, scancel, sinfo, sacct, srun, salloc, scontrol.
Choisissez la bonne technique : Job simple, interactif, array, dépendances, parallèle (OpenMP/MPI), GPU.
Analysez et optimisez : Ne vous contentez pas d’un job qui "marche", cherchez à le faire tourner bien.
La Règle d’Or : Comprendre votre application est aussi important que comprendre SLURM.
N’ayez pas peur d’expérimenter (sur des petits cas, dans les partitions de test !) et de demander de l’aide (documentation locale, support, collègues).
Pour Aller Encore Plus Loin : Explorez les conteneurs (Singularity/Apptainer) pour gérer des environnements logiciels complexes, ou les outils de gestion de workflows (Snakemake, Nextflow, …) pour orchestrer des pipelines de calculs avec de nombreuses dépendances.
Récapitulatif Options #SBATCH Courantes :
--job-name, --output, --error, --time, --nodes, --ntasks, --cpus-per-task, --mem, --mem-per-cpu, --partition, --gres, --dependency, --array, --mail-type, --mail-user.
Récapitulatif Commandes SLURM Essentielles :
sbatch, squeue, scancel, sinfo, sacct, srun, salloc, scontrol, seff (si dispo), sshare (si dispo).
Liens Utiles :
Documentation Officielle SLURM : [https://slurm.schedmd.com/](https://slurm.schedmd.com/) (Très complète, mais technique)