SLURM : aide-mémoire en questions

J’utilise SLURM depuis assez récemment et j’avais stocké les commandes que j’utilise tout le temps dans un fichier texte. J’ai remis les choses en ordre pour en faire un petit aide-mémoire. Comme pour le billet que j’avais fait sur Git, je traite d’abord les problèmes courants du plus simple au plus avancé, ensuite j’aborde des références thématiques pour aller plus loin.


Problèmes courants

Je démarre

Je veux lancer mon premier script sur le cluster

Créer un fichier job.sh :

#!/bin/bash
#SBATCH --job-name=mon-job
#SBATCH --output=logs/%j.out      # %j = identifiant du job
#SBATCH --error=logs/%j.err
#SBATCH --time=01:00:00           # Durée max : 1 heure
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=4
#SBATCH --mem=16G

python mon_script.py
mkdir -p logs
sbatch job.sh

Je ne sais pas si mon job tourne

squeue -u $USER                   # Jobs en cours ou en attente
squeue -u $USER -l                # Version longue (état, nœud, temps restant)

États courants : PD (en attente), R (en cours), CG (en fin d’exécution).


Je veux voir ce qui est disponible sur le cluster

sinfo                             # Partitions et état des nœuds
sinfo -o "%P %a %l %D %t %N"     # Vue compacte

Mon job ne démarre pas

Mon job est bloqué en PD (pending) depuis longtemps

squeue -u $USER --start           # Estimation du démarrage
scontrol show job <JOBID>         # Raison du blocage (champ "Reason")

Raisons fréquentes :

Raison Cause
Resources Ressources demandées pas encore disponibles
Priority D’autres jobs ont priorité
QOSMaxCpuPerUserLimit Quota CPU utilisateur atteint
ReqNodeNotAvail Nœud demandé hors service

Mon job est refusé à la soumission

Vérifier les limites de la partition :

scontrol show partition <nom>     # Limites de temps, CPU, mémoire
sacctmgr show user $USER          # Quotas associés au compte

Je veux lancer un job interactif pour tester

srun --ntasks=1 --cpus-per-task=4 --mem=8G --time=01:00:00 --pty bash

Sur Jean Zay, spécifier la partition :

srun --partition=gpu_p1 --gres=gpu:1 --time=00:30:00 --pty bash

Mon job a planté

Mon job s’est terminé mais je ne sais pas pourquoi

sacct -j <JOBID> --format=JobID,State,ExitCode,Elapsed,MaxRSS

États d’échec courants :

État Cause probable
FAILED Erreur dans le script (voir .err)
TIMEOUT Temps limite dépassé
OUT_OF_MEMORY Mémoire insuffisante
CANCELLED Annulé manuellement ou par l’admin
cat logs/<JOBID>.err              # Lire la sortie d'erreur

Mon job a été tué pour dépassement mémoire

Augmenter --mem dans le script. Pour estimer la mémoire réellement utilisée :

sacct -j <JOBID> --format=MaxRSS  # Pic mémoire du job terminé

MaxRSS est en Ko. Ajouter une marge de 20-30 % pour la soumission suivante.


Mon job a été tué par TIMEOUT

Augmenter --time ou découper le calcul en étapes avec des checkpoints.

Pour connaître la durée maximale autorisée sur une partition :

scontrol show partition <nom> | grep MaxTime

Je veux annuler un job

scancel <JOBID>                   # Annuler un job précis
scancel -u $USER                  # Annuler tous ses jobs
scancel --name=mon-job            # Annuler par nom

Je veux optimiser mes soumissions

Je veux lancer le même script avec des paramètres différents (sweep)

Utiliser un array job :

#!/bin/bash
#SBATCH --job-name=sweep
#SBATCH --array=0-9               # 10 jobs : indices 0 à 9
#SBATCH --output=logs/%A_%a.out   # %A = job array ID, %a = index
#SBATCH --time=00:30:00
#SBATCH --mem=8G

python train.py --seed $SLURM_ARRAY_TASK_ID

Avec une liste de valeurs :

#SBATCH --array=1,5,10,50,100

Limiter le nombre de jobs simultanés :

#SBATCH --array=0-99%10           # 100 jobs, 10 en parallèle max

Je veux utiliser un GPU

#!/bin/bash
#SBATCH --partition=gpu           # Nom de la partition GPU (varie selon le cluster)
#SBATCH --gres=gpu:1              # 1 GPU
#SBATCH --gres=gpu:a100:2         # 2 GPU de type A100 (si disponible)
#SBATCH --cpus-per-task=8         # CPUs associés (en général 8-10 par GPU)
#SBATCH --mem=40G

Vérifier que le GPU est bien alloué depuis le job :

nvidia-smi
echo $CUDA_VISIBLE_DEVICES

Je veux utiliser plusieurs nœuds (MPI)

#SBATCH --nodes=4
#SBATCH --ntasks-per-node=32
#SBATCH --cpus-per-task=1

srun python -m torch.distributed.launch --nproc_per_node=32 train_dist.py

Mon environnement conda n’est pas chargé dans le job

Les jobs SLURM ne sourcent pas .bashrc par défaut. Initialiser conda explicitement :

#!/bin/bash
#SBATCH ...

source ~/.bashrc                          # ou :
source /path/to/miniconda3/etc/profile.d/conda.sh
conda activate mon-env

python mon_script.py

Je veux charger des modules logiciels

module avail                      # Lister les modules disponibles
module load python/3.11 cuda/12.1
module list                       # Modules chargés
module purge                      # Décharger tout

Dans le script SLURM :

#!/bin/bash
#SBATCH ...

module purge
module load python/3.11 cuda/12.1
source ~/.venv/bin/activate
python mon_script.py

Écrire un script SLURM

Débutant

Les directives #SBATCH essentielles

#SBATCH --job-name=nom            # Nom affiché dans squeue
#SBATCH --output=logs/%j.out      # Sortie standard (%j = JOBID)
#SBATCH --error=logs/%j.err       # Sortie d'erreur
#SBATCH --time=HH:MM:SS           # Durée maximale
#SBATCH --ntasks=1                # Nombre de tâches (processus MPI)
#SBATCH --cpus-per-task=4         # CPUs par tâche (threads OpenMP)
#SBATCH --mem=16G                 # Mémoire totale par nœud

Rediriger les sorties dans un seul fichier

#SBATCH --output=logs/%j.log      # stdout et stderr dans le même fichier

Ou depuis la ligne de commande :

sbatch --output=logs/test.log job.sh

Recevoir un email à la fin du job

#SBATCH --mail-type=END,FAIL
#SBATCH --mail-user=vous@labo.fr

Valeurs possibles : BEGIN, END, FAIL, ALL.


Intermédiaire

Spécifier une partition et un compte

Sur les clusters nationaux, les heures sont décomptées par projet (compte) :

#SBATCH --partition=gpu_p2
#SBATCH --account=abc1234         # Code projet DARI/GENCI

Utiliser des variables d’environnement SLURM dans le script

echo "Job ID      : $SLURM_JOB_ID"
echo "Nœud        : $SLURM_JOB_NODELIST"
echo "CPUs alloués : $SLURM_CPUS_PER_TASK"
echo "Array index : $SLURM_ARRAY_TASK_ID"

Copier les données vers le scratch local avant le calcul

Sur les grands clusters, les I/O sur le stockage partagé sont coûteuses. Utiliser le scratch local du nœud :

SCRATCH=$SLURM_TMPDIR             # Variable fournie par SLURM sur certains clusters
cp -r $HOME/data/dataset/ $SCRATCH/
python train.py --data $SCRATCH/dataset/

Sur Jean Zay : $SCRATCH et $STORE sont les espaces recommandés pour les données.


Avancé

Reprendre un calcul interrompu (checkpointing)

Sauvegarder l’état régulièrement dans le script Python :

# Sauvegarder toutes les N epochs
if epoch % save_every == 0:
    torch.save({"epoch": epoch, "model": model.state_dict()}, "checkpoint.pt")

Dans le script SLURM, reprendre si un checkpoint existe :

if [ -f checkpoint.pt ]; then
    python train.py --resume checkpoint.pt
else
    python train.py
fi

Monitoring & Débogage

Débutant

Suivre l’avancement d’un job en temps réel

tail -f logs/<JOBID>.out          # Suivre la sortie en direct
watch -n 5 squeue -u $USER        # Rafraîchir squeue toutes les 5 secondes

Voir les ressources consommées par un job terminé

sacct -j <JOBID> --format=JobID,JobName,State,Elapsed,CPUTime,MaxRSS,ExitCode

Intermédiaire

Voir l’utilisation en temps réel d’un job qui tourne

srun --jobid=<JOBID> --pty bash   # Se connecter au nœud du job
# Puis :
top -u $USER
nvidia-smi                        # Si GPU

Ou directement :

ssh $(squeue -j <JOBID> -o "%N" --noheader)   # Se connecter au nœud

Estimer l’efficacité d’un job

seff <JOBID>                      # Résumé CPU efficiency + mémoire (si disponible)

Un job efficace utilise > 80 % des CPUs alloués et < 90 % de la mémoire demandée.


Consulter l’historique de ses jobs

sacct -u $USER --starttime=2025-01-01 --format=JobID,JobName,State,Elapsed,CPUTime
sacct -u $USER --starttime=now-7days  # Dernière semaine

Avancé

Connaître sa consommation d’heures de calcul

sreport cluster AccountUtilizationByUser start=2025-01-01 end=now
# Sur Jean Zay :
idrquota                          # Outil spécifique IDRIS

Diagnostiquer un nœud défaillant

scontrol show node <nom-noeud>    # État détaillé d'un nœud
sinfo -n <nom-noeud>              # Rapide

Configuration et environnement

Débutant

Configurer son environnement par défaut pour SLURM

Créer un fichier ~/.slurm/defaults (si supporté par le cluster) ou factoriser les options communes dans un script source :

# config_slurm.sh — à sourcer en début de script
BASE_ARGS="--account=abc1234 --partition=gpu_p2 --mail-user=vous@labo.fr --mail-type=FAIL"

Intermédiaire

Utiliser un environnement reproductible avec conda

# Créer l'environnement une fois sur le nœud de login
conda env create -f environment.yml
conda activate mon-env
pip install -e .

# Dans le script SLURM
source ~/.bashrc
conda activate mon-env

Pour éviter les problèmes de PATH, toujours utiliser le chemin absolu de l’interpréteur :

PYTHON=$(which python)
$PYTHON mon_script.py

Références