Exécution d'un code parallèle en batch
Les travaux sont gérés sur l'ensemble des nœuds par le logiciel Slurm.
Si votre code requiert la fonctionnalité MPI CUDA-aware, vous devez vous référer à la page exécution d'un travail multi GPU MPI CUDA-aware et GPUDirect en batch.
Pour soumettre un travail parallèle en batch sur Jean Zay, il faut :
- Créer un script de soumission :
- Exemple CPU
- Exemple V100 quadri-GPU
- Exemple V100 octo-GPU
- Exemple A100 octo-GPU
- Exemple H100 quadri-GPU
#!/bin/bash
#SBATCH --job-name=TravailMPI # nom du job
#SBATCH --nodes=2 # Nombre total de noeuds
#SBATCH --ntasks-per-node=40 # Nombre de processus MPI par noeud
# /!\ Attention, la ligne suivante est trompeuse mais dans le vocabulaire
# de Slurm "multithread" fait bien référence à l'hyperthreading.
#SBATCH --hint=nomultithread # 1 processus MPI par coeur physique (pas d'hyperthreading)
#SBATCH --time=00:10:00 # Temps d’exécution maximum demande (HH:MM:SS)
#SBATCH --output=TravailMPI%j.out # Nom du fichier de sortie (%j est remplacé par le numéro du travail)
#SBATCH --error=TravailMPI%j.out # Nom du fichier d'erreur (ici commun avec la sortie)
# on se place dans le répertoire de soumission
cd ${SLURM_SUBMIT_DIR}
# nettoyage des modules charges en interactif et herites par defaut
module purge
# chargement des modules
module load ... # par exemple intel-all/19.0.4
# echo des commandes lancées
set -x
# exécution du code
srun ./exec_mpi
La configuration actuelle de la machine ne permet pas d'utiliser l'hyperthreading (exécution de 80 processus MPI sur les 40 cœurs d'un nœud de calcul) avec un code purement MPI.
#!/bin/bash
#SBATCH --job-name=multi_gpu # nom du job
# Il est possible d'utiliser uniquement des GPU V100 16 Go ou 32 Go
##SBATCH -C v100-16g # decommenter pour reserver uniquement des GPU V100 16 Go
##SBATCH -C v100-32g # decommenter pour reserver uniquement des GPU V100 32 Go
# Ici, reservation de 2 noeuds avec 4 GPU par noeud et 10 CPU par tache :
#SBATCH --nodes=2 # nombre de noeuds
#SBATCH --ntasks-per-node=4 # nombre de taches par noeud (= nombre de GPU par noeud ici)
#SBATCH --gres=gpu:4 # nombre de GPU par noeud (max 4)
# Le nombre de CPU par tache doit etre adapte en fonction de la partition utilisee. Sachant
# qu'ici on reserve un GPU par tache (soit 1/4 des GPU du noeud), l'ideal est de reserver 1/4
# des CPU du noeud par tache :
#SBATCH --cpus-per-task=10 # nombre de CPU par tache (1/4 des CPU du noeud 4-GPU V100)
# /!\ Attention, "multithread" fait reference à l'hyperthreading dans la terminologie Slurm
#SBATCH --hint=nomultithread # hyperthreading desactive
#SBATCH --time=00:10:00 # temps maximum d'execution demande (HH:MM:SS)
#SBATCH --output=multi_gpu%j.out # nom du fichier de sortie (%j est remplacé par le numéro du travail)
#SBATCH --error=multi_gpu%j.out # nom du fichier d'erreur (ici commun avec la sortie)
# Nettoyage des modules charges en interactif et herites par defaut
module purge
# Chargement des modules
module load ...
# Echo des commandes lancees
set -x
# Le code doit etre compile avec les modules compatibles avec la partition choisie
# Execution du code
srun ./executable_multi_gpu
# Execution du code via bind_gpu.sh si necessite d'un binding externe
# avec un GPU par tache, voir les remarques
# srun /lustre/fshomisc/sup/pub/idrtools/bind_gpu.sh ./executable_multi_gpu
# Pour lancer un script Python, il faut remplacer la dernière ligne par
# srun python -u script_multi_gpu.py
# L'option -u (pour unbuffered) de Python permet de désactiver la bufférisation des sorties standards
#!/bin/bash
#SBATCH --job-name=multi_gpu # nom du job
#SBATCH --partition=gpu_p2 # partition gpu_p2 : noeud octo-GPU V100 32 Go
# Ici, reservation de 2 noeuds avec 8 GPU par noeud et 3 CPU par tache :
#SBATCH --nodes=2 # nombre de noeuds
#SBATCH --ntasks-per-node=8 # nombre de taches par noeud (= nombre de GPU par noeud ici)
#SBATCH --gres=gpu:8 # nombre de GPU par noeud (max 8)
# Le nombre de CPU par tache doit etre adapte en fonction de la partition utilisee. Sachant
# qu'ici on reserve un GPU par tache (soit 1/8 des GPU du noeud), l'ideal est de reserver 1/8
# des CPU du noeud par tache :
#SBATCH --cpus-per-task=3 # nombre de CPU par tache (1/8 des CPU du noeud 8-GPU V100)
# /!\ Attention, "multithread" fait reference à l'hyperthreading dans la terminologie Slurm
#SBATCH --hint=nomultithread # hyperthreading desactive
#SBATCH --time=00:10:00 # temps maximum d'execution demande (HH:MM:SS)
#SBATCH --output=multi_gpu%j.out # nom du fichier de sortie (%j est remplacé par le numéro du travail)
#SBATCH --error=multi_gpu%j.out # nom du fichier d'erreur (ici commun avec la sortie)
# Nettoyage des modules charges en interactif et herites par defaut
module purge
# Chargement des modules
module load ...
# Echo des commandes lancees
set -x
# Le code doit etre compile avec les modules compatibles avec la partition choisie
# Execution du code
srun ./executable_multi_gpu
# Execution du code via bind_gpu.sh si necessite d'un binding externe
# avec un GPU par tache, voir les remarques
# srun /lustre/fshomisc/sup/pub/idrtools/bind_gpu.sh ./executable_multi_gpu
# Pour lancer un script Python, il faut remplacer la dernière ligne par
# srun python -u script_multi_gpu.py
# L'option -u (pour unbuffered) de Python permet de désactiver la bufférisation des sorties standards
#!/bin/bash
#SBATCH --job-name=multi_gpu # nom du job
#SBATCH -C a100 # partition gpu_p5 : noeud octo-GPU A100 80 Go
# Ici, reservation de 2 noeuds avec 8 GPU par noeud et 8 CPU par tache :
#SBATCH --nodes=2 # nombre de noeuds
#SBATCH --ntasks-per-node=8 # nombre de taches par noeud (= nombre de GPU par noeud ici)
#SBATCH --gres=gpu:8 # nombre de GPU par noeud (max 8)
# Le nombre de CPU par tache doit etre adapte en fonction de la partition utilisee. Sachant
# qu'ici on reserve un GPU par tache (soit 1/8 des GPU du noeud), l'ideal est de reserver 1/8
# des CPU du noeud par tache :
#SBATCH --cpus-per-task=8 # nombre de CPU par tache pour gpu_p5 (1/8 des CPU du noeud 8-GPU A100)
# /!\ Attention, "multithread" fait reference à l'hyperthreading dans la terminologie Slurm
#SBATCH --hint=nomultithread # hyperthreading desactive
#SBATCH --time=00:10:00 # temps maximum d'execution demande (HH:MM:SS)
#SBATCH --output=multi_gpu%j.out # nom du fichier de sortie (%j est remplacé par le numéro du travail)
#SBATCH --error=multi_gpu%j.out # nom du fichier d'erreur (ici commun avec la sortie)
# Nettoyage des modules charges en interactif et herites par defaut
module purge
# Activation du module permet l'accès aux modules compatibles avec la partition A100
module load arch/a100
# Chargement des modules
module load ...
# Echo des commandes lancees
set -x
# Le code doit etre compile avec les modules compatibles avec la partition choisie
# Execution du code
srun ./executable_multi_gpu
# Execution du code via bind_gpu.sh si necessite d'un binding externe
# avec un GPU par tache, voir les remarques
# srun /lustre/fshomisc/sup/pub/idrtools/bind_gpu.sh ./executable_multi_gpu
# Pour lancer un script Python, il faut remplacer la dernière ligne par
# srun python -u script_multi_gpu.py
# L'option -u (pour unbuffered) de Python permet de désactiver la bufférisation des sorties standards
Les modules accessibles par défaut ne sont pas compatibles avec cette partition,
il est nécessaire de charger préalablement le module arch/a100 pour pouvoir lister
et charger les modules compatibles. Pour en savoir plus, consultez la section
Modules compatibles avec la partition A100.
#!/bin/bash
#SBATCH --job-name=multi_gpu # nom du job
#SBATCH -C h100 # partition gpu_p6 : noeud quadri-GPU H100 80 Go
# Ici, reservation de 2 noeuds avec 4 GPU par noeud et 24 CPU par tache :
#SBATCH --nodes=2 # nombre de noeuds
#SBATCH --ntasks-per-node=4 # nombre de taches par noeud (= nombre de GPU par noeud ici)
#SBATCH --gres=gpu:4 # nombre de GPU par noeud (max 4)
# Le nombre de CPU par tache doit etre adapte en fonction de la partition utilisee. Sachant
# qu'ici on reserve un GPU par tache (soit 1/4 des GPU du noeud), l'ideal est de reserver 1/4
# des CPU du noeud par tache :
#SBATCH --cpus-per-task=24 # nombre de CPU par tache pour gpu_p6 (1/4 des CPU du noeud 4-GPU H100)
# /!\ Attention, "multithread" fait reference à l'hyperthreading dans la terminologie Slurm
#SBATCH --hint=nomultithread # hyperthreading desactive
#SBATCH --time=00:10:00 # temps maximum d'execution demande (HH:MM:SS)
#SBATCH --output=multi_gpu%j.out # nom du fichier de sortie (%j est remplacé par le numéro du travail)
#SBATCH --error=multi_gpu%j.out # nom du fichier d'erreur (ici commun avec la sortie)
# Nettoyage des modules charges en interactif et herites par defaut
module purge
# Activation du module permet l'accès aux modules compatibles avec la partition H100
module load arch/h100
# Chargement des modules
module load ...
# Echo des commandes lancees
set -x
# Le code doit etre compile avec les modules compatibles avec la partition choisie
# Execution du code
srun ./executable_multi_gpu
# Execution du code via bind_gpu.sh si necessite d'un binding externe
# avec un GPU par tache, voir les remarques
# srun /lustre/fshomisc/sup/pub/idrtools/bind_gpu.sh ./executable_multi_gpu
# Pour lancer un script Python, il faut remplacer la dernière ligne par
# srun python -u script_multi_gpu.py
# L'option -u (pour unbuffered) de Python permet de désactiver la bufférisation des sorties standards
Les modules accessibles par défaut ne sont pas compatibles avec cette partition,
il est nécessaire de charger préalablement le module arch/h100 pour pouvoir lister
et charger les modules compatibles. Pour en savoir plus, consultez la section
Modules compatibles avec la partition H100.
- Soumettre ce script via la commande
sbatch:
sbatch mon_script.slurm
Remarques :
- Nous vous recommandons de compiler et d'exécuter votre code dans un même environnement logiciel en chargeant les mêmes modules.
- L'option
--hint=nomultithreadassure la réservation des cœurs physiques (pas d'hyperthreading). - La mémoire allouée pour le job est proportionnelle au nombre de cœurs CPU demandés. Par exemple, si vous demandez 1/4 des cœurs CPU physiques d'un nœud, vous aurez accès à 1/4 de sa mémoire RAM. Il est important d'être cohérent avec la configuration des nœuds utilisés pour éviter une surfacturation d'heures, tout en profitant de la mémoire à laquelle vous avez le droit. Vous pouvez consulter notre documentation à ce sujet : Allocation mémoire avec Slurm.
- Dans ces exemples, on suppose que l'exécutable ou le script Python utilisé
se situe dans le répertoire de soumission, c'est-à-dire le répertoire dans
lequel on se situe au moment d'utiliser la commande
sbatch: la variable$SLURM_SUBMIT_DIRest automatiquement valorisée par Slurm. - Le fichier de sortie du calcul se trouvera également dans le répertoire de soumission. Il est créé dès le début de l'exécution du travail; l'éditer ou le modifier pendant le déroulement du travail peut perturber celui-ci.
- le
module purgeest rendu indispensable par le comportement par défaut de Slurm : les modules que vous avez chargés dans votre environnement au moment où vous lancezsbatchsont pris en compte dans le job soumis. - L'usage de la commande
srunest indispensable lorsque vous demandez une exécution multi-tâches. Nous déconseillons l'usage dempirunsur Jean Zay, seulesrungarantit une distribution conforme aux spécifications de ressources demandées dans votre fichier de soumission. - Le script
/lustre/fshomisc/sup/pub/idrtools/bind_gpu.shpermet d'associer un GPU différent à chaque processus. Il n'est pas nécessaire de l'utiliser si votre code gère explicitement l'association des processus aux GPU. Attention, ce script est très basique et ne permet de gérer que le cas simple 1 GPU pour 1 tâche MPI. Il ne fonctionne donc que pour un nombre de tâches par nœud inférieur ou égal au nombre de GPU par nœud. - Les travaux ont tous des ressources définies par une partition et une "Qualité de Service" QoS (Quality of Service) positionnées par défaut dans Slurm. Vous pouvez en modifier les limites en spécifiant une partition et/ou une QoS comme indiqué dans notre documentation détaillant les partitions et les Qos CPU et GPU.
- Pour les comptes multi-projets ainsi que ceux ayant des heures CPU et GPU, il est indispensable de spécifier l'attribution d'heures sur laquelle décompter les heures de calcul du travail comme indiqué dans notre documentation détaillant la gestion des heures de calcul pour vous assurer que les heures consommées par vos travaux soient décomptées de la bonne attribution.