SLURM - Script de soumission

Vous trouverez ci-dessous un certain nombre d’exemples de scripts pouvant être utilisés comme modèle pour créer vos propres scripts de soumission SLURM.

Simple scripts de soumission

Les jobs nécessitent un fichier de script que SLURM interprète et exécute.

Le fichier SBATCH contient à la fois des commandes spécifiques à SLURM à interpréter ainsi que des programmes à exécuter. Vous trouverez ci-dessous un exemple simple d’un job pour exécuter un fichier Stata do.

Script

Ce fichier est nommé myscript.sbatch :

#!/bin/bash
#SBATCH --mynodes=1
#SBATCH --ntasks-per-mynode=1
#SBATCH --cpus-per-task=1
#SBATCH --time=5:00:00
#SBATCH --mem=2GB
#SBATCH --job-name=myTest
#SBATCH --mail-type=END
#SBATCH [email protected]
#SBATCH --output=slurm_%j.out

module purge
module load stata/14.2
RUNDIR=$SCRATCH/my_project/run-${SLURM_JOB_ID/.*}
mkdir -p $RUNDIR
DATADIR=$SCRATCH/my_project/data
cd $RUNDIR
stata -b do $DATADIR/data_0706.do

Script détaillé

Le même script avec les lignes commentées :

## Indique au shell comment exécuter le script
#!/bin/bash

## Les lignes #SBATCH sont lues par SLURM pour les options
## Dans les lignes ci-dessous, nous demandons un seul nœud, une tâche pour ce nœud et un processeur pour chaque tâche
#SBATCH --mynodes=1
#SBATCH --ntasks-per-mynode=1
#SBATCH --cpus-per-task=1

## Temps estimé pour terminer, ici 5 heures.
#SBATCH --time=5:00:00

## Estimation qu'il ne faudra pas plus de 2 Go de mémoire
#SBATCH --mem=2GB

## Pour les rendre plus faciles à suivre, il est préférable de nommer les jobs de manière reconnaissable
## Vous pouvez ensuite utiliser le nom pour rechercher des logs/repports avec la commande squeue.
#SBATCH --job-name=myTest

## Alertes par e-mail indiquant quand le job se termine et à qui l'e-mail doit être envoyé.
#SBATCH --mail-type=END
#SBATCH [email protected]

## Place la sortie standard et l'erreur standard dans le même fichier, ici slurm_<job_id>.out.
## Le %j dans la ligne --output indique à SLURM d'utiliser l'ID du job dans le nom du fichier de sortie.
## Vous pouvez également ajouter une ligne -e ou --error pour séparer les journaux de sortie et d'erreur
#SBATCH --output=slurm_%j.out

## Assurer un environnement propre en purgeant l'actuel
module purge

## Chargez le logiciel/module souhaité, ici stata 14.2
module load stata/14.2

## Création d'un répertoire unique dans lequel exécuter le job
RUNDIR=$SCRATCH/my_project/run-${SLURM_JOB_ID/.*}
mkdir -p $RUNDIR

## Définir une variable d'environnement pour l'endroit où les données sont stockées
DATADIR=$SCRATCH/my_project/data

## Remplacer les répertoires par un unique répertoire d'exécution
cd $RUNDIR

## Exécuter le script de fichier Stata do souhaité
stata -b do $DATADIR/data_0706.do

Appel d’un script python

Exemple avec un script python :

#!/bin/bash
#SBATCH --job-name=serial_job_test # Job name
#SBATCH --mail-type=END,FAIL # Mail events (NONE, BEGIN, END, FAIL, ALL)
#SBATCH [email protected] # Where to send mail
#SBATCH --ntasks=1 # Run on a single CPU
#SBATCH --mem=1gb # Job memory request
#SBATCH --time=00:05:00 # Time limit hrs:min:sec
#SBATCH --output=serial_test_%j.log # Standard output and error log
pwd; hostname; date

module load python

echo "Running plot script on a single CPU core"

python /data/training/SLURM/plot_template.py

date

Lancer un job

Vous pouvez envoyer le job avec la commande suivante qui entraînera la mise en file d’attente du job en attendant que les ressources soient disponibles (ce qui varie en fonction du nombre d’autres jobs exécutés sur le cluster). :

# sbatch monscript.sbatch

Vous pouvez voir l’état de vos jobs avec la commande suivante :

# squeue  -u $USER

Enfin, vous pouvez lire la sortie de votre job dans le fichier slurm-<job_ID>.out produit en exécutant votre job. C’est là que se trouvent les journaux concernant l’exécution de votre job, y compris les erreurs ou les messages système. Vous pouvez imprimer le contenu à l’écran à partir du répertoire contenant le fichier de sortie avec la commande suivante :

# cat slurm-<job_ID>.out

Jobs interactifs

La majorité des jobs sur un cluster sont soumis avec la commande sbatch et exécutés en arrière-plan mais il existe des méthodes pour les exécuter interactivement via la commande srun.
Les jobs interactifs permettent aux utilisateurs de saisir des commandes et des données via le terminal (ou dans une interface graphique).

Il est possible en mode interactif de :

  • Éditer des fichiers
  • Compiler et débuger le code
  • Explorer les données
  • Obtenir des fenêtres graphiques
  • Exécuter d’autres logiciels

Les jobs interactifs permettent également d’éviter les problèmes avec les nœuds. Si vous joblez sur un nœud et que votre job est trop gourmand en IO, il peut être supprimé sans préavis. L’exécution de jobs inteinteractifs sur des nœuds n’impacte généralement pas beaucoup d’utilisateurs et permet donc d’accéder à des ressources qui ne serait pas disponibles en temps normal, comme l’accès interactif aux GPU, la mémoire, l’accès exclusif à toutes les ressources, etc.

Lancer un job interactif

Dans les exemples ci-dessous, on lance une session shell avec --pty /bin/bash. Par défaut ici, la ressource allouée est 1 seul processeur et 2 Go de mémoire pendant 1h.

# srun --pty /bin/bash

Pour demander 4 processeurs, 4 Go de mémoire et une durée d’exécution de 2h, on ajoute les arguments suivants :

# srun --cpus-per-task=4 --time=2:00:00 --mem=4000 --pty /bin/bash

Pour utiliser le GPU, 3 Go de mémoire et une durée de fonctionnement de 1h30, vous pouvez ajouter les éléments suivants :

# srun --time=1:30:00 --mem=3000 --gres=gpu:1 --pty /bin/bash

Une fois le job lancé, l’invite de commande change, ici on passe de master-3 à mynode80, donc on ne se trouve plus sur le master mais sur le noeud mynode80, on peut maintenant charger des modules/logiciels et les exécuter interactivement sans impacter le cluster :

[martymcfly@master-3 ~]# srun --pty /bin/bash
srun: job 6658996 queued and waiting for resources
srun: job 6658996 has been allocated resources
[martymcfly@mynode80 ~]$

Exemple avec R

Exemple : étapes pour démarrer une session interactive et lancer R, là encore on lance le job depuis le master, on se retrouve connecté sur le noeud, on paramètre les module, on lance R et la commande exit nous fait revenir sur le master :

[emmetbrown@master-1 ~]# srun --cpus-per-task=1 --pty /bin/bash
[emmetbrown@mynode22 ~]# module purge
[emmetbrown@mynode22 ~]# module load r/intel/4.0.3
[emmetbrown@mynode22 ~]# module list
Currently Loaded Modules:
1) intel/19.1.2 2) r/intel/4.0.3
[emmetbrown@mynode22 ~]# R
R version 4.0.3 (2020-10-10) -- "Bunny-Wunnies Freak Out"
Copyright (C) 2020 The R Foundation for Statistical Computing
Platform: x86_64-centos-linux-gnu (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
Natural language support but running in an English locale
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
> 5 + 10
[1] 15
> q()
Save workspace image? [y/n/c]: n
[emmetbrown@mynode22 ~]# exit
exit
[emmetbrown@master-1 ~]$

Job MPI

MPI (Message Passing Interface) est géré par un programme comme OpenMPI pour coordonner le code et les ressources dans le cluster HPC afin qu’un job puisse s’exécuter en parallèle (en lançant des precessus en parallèle).

Pour utiliser MPI il faut utiliser un compilateur MPI, exemple avec Greene, qui prend en charge 2 versions d’OpenMPI, Intel et GCC.

Module

Pour appeller le module OpenMPI avec Intel :

# module load openmpi/intel/4.1.1 

Avec GCC :

# module load openmpi/gcc/4.1.1

Exemple

Exemple de compilation d’un script en C pour MPI. A placer dans votre répertoire de travail sous le nom de hellompi.c :

#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
int main(int argc, char *argv[], char *envp[]) {
int numprocs, rank, namelen;
char processor_name[MPI_MAX_PROCESSOR_NAME];

MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Get_processor_name(processor_name, &namelen);

printf("Process %d on %s out of %d\n", rank, processor_name, numprocs);

MPI_Finalize();
}

Puis charger le module et compiler :

# module load openmpi/intel/4.1.1
# mpicc hellompi.c -o hellompi

Ensuite on crée le script, nommé hellompi.sbatch :

#!/bin/bash
#SBATCH --nodes=4
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --time=1:00:00
#SBATCH --mem=2GB
#SBATCH --job-name=hellompi
#SBATCH --output=hellompi.out

# Load the default OpenMPI module.
module purge
module load openmpi/intel/4.1.1

# Run the hellompi program with mpirun. The -n flag is not required;
# mpirun will automatically figure out the best configuration from the
# Slurm environment variables.
mpirun ./hellompi

Lancer le script

Pour lancer votre script, on utilise simplement sbatch :

# sbatch hellompi.sbatch

Après l’exécution du job, lancer cat hellompi.out pour voir que vos processus ont été exécutés sur plusieurs nœuds. Il peut y avoir des erreurs, mais votre sortie doit contenir quelque chose comme ce qui suit, indiquant que le processus a été exécuté en parallèle sur plusieurs nœuds :

Process 0 on mynode05.hpc.cluster out of 4
Process 1 on mynode06.hpc.cluster out of 4
Process 2 on mynode07.hpc.cluster out of 4
Process 3 on mynode08.hpc.cluster out of 4

Job GPU

Pour utiliser la GPU, il faut préciser dans le script la directive SBATCH suivante :

#SBATCH --gres=gpu:1

Pour demander une GPU spécifique, par exemple une RTX 800 :

#SBATCH --gres=gpu:rtx800:1

Script

Le contenu du script de travail “run-amber.s” doit être le suivant :

#!/bin/bash
#
#SBATCH --job-name=myAmberJobGPU
#SBATCH --nodes=1
#SBATCH --cpus-per-task=1
#SBATCH --time=00:30:00
#SBATCH --mem=3GB
#SBATCH --gres=gpu:1
module purge
module load amber/openmpi/intel/20.06
cd /scratch/$USER/myambertest
pmemd.cuda -O

Lancer le script

Pour soumettre un job “Amber” (progiciel de dynamique moléculaire) :

# sbatch run-amber.s
Submitted batch job 14257

Lorsque le job est terminé, plusieurs fichiers de sortie sont générés. Vérifiez celui nommé mdout :

|--------------------- INFORMATION ---------------------- 
| GPU (CUDA) Version of PMEMD in use: NVIDIA GPU IN USE.
| Version 16.0.0
|
| 02/25/2016
[......]

|------------------- GPU DEVICE INFO --------------------
|
| CUDA_VISIBLE_DEVICES: 0
| CUDA Capable Devices Detected: 1
| CUDA Device ID in use: 0
| CUDA Device Name: Tesla V100
| CUDA Device Global Mem Size: 11439 MB
| CUDA Device Num Multiprocessors: 13
| CUDA Device Core Freq: 0.82 GHz
|
|--------------------------------------------------------

Job Array

Les jobs array permettent de soumettre de nombreux jobs similaires avec des exigences de travail (presque) identiques et réduire les charges pour les utilisateurs et l’ordonnanceur.
Les obs array ne peuvent être utilisés qu’avec sbatch.

Script

Dans cet exemple il y 5 fichiers d’entrée sample-1.txt à sample-5.txt.

Contenu du répertoire :

# mkdir -p /scratch/$USER/myjarraytest
# cd /scratch/$USER/myjarraytest
# cp /share/apps/Tutorials/slurm/example/jobarray/* .
# ls
run-jobarray.s sample-1.txt sample-2.txt sample-3.txt sample-4.txt sample-5.txt wordcount.py

Les jobs array créent la variable d’environnement SLURM_ARRAY_TASK_ID qui est unique pour chaque job array. Les options %A et %a indiquent l’ID du job et l’ID de l’index du tableau.

Le contenu du script ‘run-jobarray.s’ est le suivant :

#!/bin/bash
#
#SBATCH --job-name=myJobarrayTest
#SBATCH --nodes=1
#SBATCH --tasks-per-node=1
#SBATCH --array=1-5 ############## create an array
#SBATCH --time=5:00
#SBATCH --mem=1GB
#SBATCH --output=wordcounts_%A_%a.out
#SBATCH --error=wordcounts_%A_%a.err
module purge
module load python/intel/3.8.6
cd /scratch/$USER/myjarraytest
python2 wordcount.py sample-$SLURM_ARRAY_TASK_ID.txt

Lancer le script

Pour soumettre la tâche sur le cluster, En exécutant la commande sbatch --array=1-5 run-jobarray.s, on soumet 5 jobs pour traiter chaque fichiers d’entrée individuellement.  :

# sbatch --array=1-5 run-jobarray.s

Documentation

https://help.rc.ufl.edu/doc/Sample_SLURM_Scripts
https://help.jasmin.ac.uk/article/4890-how-to-submit-a-job-to-slurm
https://docs-research-it.berkeley.edu/services/high-performance-computing/user-guide/running-your-jobs/scheduler-examples/
https://slurm.schedmd.com/sbatch.html
https://sites.google.com/nyu.edu/nyu-hpc/training-support/tutorials/slurm-tutorial?pli=1
https://sites.google.com/nyu.edu/nyu-hpc/training-support/general-hpc-topics/slurm-submitting-jobs

> Partager <