Jean Zay : Utilisation des conteneurs via Singularity

Présentation

Singularity est un système de conteneurisation multi-plateformes open source développé par Sylabs. L’un des principaux avantages de Singularity est de permettre la reproductibilité au calcul scientifique. Cette solution est performante et très adaptée aussi bien pour le calcul haute performance, que pour le calcul en intelligence artificielle. La reproductibilité passe par l’utilisation des conteneurs pour déplacer les applications d'un système à l'autre. À l'aide des conteneurs Singularity, les utilisateurs peuvent travailler dans des environnements reproductibles de leur choix et de leur conception, et ces environnements complets peuvent facilement être copiés et exécutés sur le supercalculateur Jean Zay.

Environnement

Singularity est accessible par la commande module :

$ module load singularity

Pour obtenir des informations sur le module Singularity, il suffit d'utiliser la commande suivante :

$ module show singularity

Environnement d'échange temporaire

Le répertoire qui va contenir de façon temporaire le filesystem du container lors de son exécution sera créé sous l’emplacement valorisé par $SINGULARITY_CACHEDIR. Une fois le module chargé, l'emplacement du cache personnel Singularity associé à la variable d’environnement $SINGULARITY_CACHEDIR est positionné automatiquement dans l’espace disque $SCRATCH. Il est donc fortement recommandé de ne pas modifier la variable d'environnement $SINGULARITY_CACHEDIR afin de ne pas dépasser les quotas des autre espaces disques et d'y en simplifier le nettoyage automatique.

Environnement d’exécution

Le répertoire de travail à partir duquel les commandes de Singularity sont lancées (build, pull, run, exec, etc…) doit être l'espace $WORK ou $SCRATCH, car c’est dans l'un de ces derniers espaces que seront stockés les fichiers ou sous-répertoires contenant un grand nombre de fichiers volumineux.

Les conteneurs autorisés à l’exécution doivent se trouver dans l'espace disque dont le chemin est positionné par la variable environnement $SINGULARITY_ALLOWED_DIR. Cette variable définit un chemin unique par utilisateur et ce chemin n'est pas modifiable. La copie et la suppression de conteneurs dans cet espace s'effectue via la commande idrcontmgr. Cette dernière autorise ou non la copie des conteneurs sur cet espace, en vérifiant au préalable si le conteneur obéit aux contraintes de sécurité définies par l'IDRIS. Cet espace est limité à 20 conteneurs.

Un conteneur pourra donc être copié dans l'espace d’exécution autorisé via la commande idrcontmgr de la manière suivante :

$ idrcontmgr cp my-container.sif

La suppression s'effectue d'une manière similaire :

$ idrcontmgr rm my-container.sif

Cette commande permet également d’afficher le contenu de l’espace d’exécution autorisé :

$ idrcontmgr ls

Construction d'une image Singularity

Les modes de construction d'images Singularity nécessitant d'être super utilisateur (root) ne sont pas disponibles sur Jean Zay. Il n'est donc pas possible de construire une image Singularity à partir d’un fichier de définition. Pour ce type d'image, il est donc laissé au soin des utilisateurs de les créer depuis une autre machine, puis de les rapatrier ensuite sur Jean Zay.

Depuis une des frontales de Jean Zay, il est toutefois permis de créer une image Singularity depuis des dépôts existants (Singularity, Docker, ect…) sous forme d'un fichier SIF.

Construction d'une image depuis un dépôt

Depuis l'espace disque $WORK ou $SCRATCH, un utilisateur peut créer une image Singularity depuis un dépôt publique existant (Singularity, Docker, etc…) en lançant la commande singularity build :

$ singularity build image-singularity-tensorflow.sif docker://tensorflow/tensorflow:latest-gpu-py3

Sur cet exemple, la commande est utilisée pour télécharger une image depuis le dépôt public Docker, pour ensuite construire une image Singularity au format SIF.

Conversion d'une image SANDBOX au format SIF

L'utilisation des conteneurs sous forme de SANDBOX n'est pas autorisée sur Jean Zay. Néanmoins, il est tout à fait possible de convertir une image SANDBOX au format SIF. Il suffit d'utiliser la commande singularity build :

$ singularity build mon_conteneur.sif mon_conteneur_sandbox/

Remarque : Les ressources en mémoire RAM étant limités à 5GB par utilisateur sur les frontales, il est fortement recommandé d'utiliser les nœuds de pré/post-traitement pour la construction ou la convertion de conteneurs nécessitants des ressources importantes.

Exécution d'un shell dans une image Singularity

La commande singularity run permet de lancer un container Singularity et un shell à l’intérieur de ce container. L’exécution de cette commande requière l'utilisation du mode interactif sur un nœud de calcul (cf. documentation d'exécution interactive d'un code CPU et GPU).

Par exemple, pour la partition CPU, il vous faudra ouvrir un terminal directement sur un nœud de calcul sur lequel des ressources vous sont réservées (ici 10 cœurs) en utilisant la commande suivante :

$ srun --pty --ntasks=1 --cpus-per-task=10 --hint=nomultithread [--other-options] bash

puis lancer le container en mode shell via la commande suivante :

$ singularity shell $SINGULARITY_ALLOWED_DIR/mon_conteneur_cpu.sif

Pour la partition GPU, la manipulation est quasi identique en allouant les bonnes ressources sur un nœud GPU (cf. documentation d'exécution interactive d'un code GPU), puis lancer le container shell comme précédemment, en utilisant l'option --nv afin de prendre en compte les cartes NVIDIA :

$ singularity shell --nv $SINGULARITY_ALLOWED_DIR/mon_conteneur_gpu.sif

Exécution d'un code depuis une image Singularity en mode batch

Exécution d'un code parallèle MPI depuis une image Singularity en mode batch

Pour soumettre un travail MPI en batch sur Jean Zay, il faut :

  • Créer un script de soumission : voici un exemple pour la partition cpu par défaut (nœuds 4-GPU avec 40 cœurs physiques), enregistré dans le fichier singularity_mpi.slurm :
    singularity_mpi.slurm
    #!/bin/bash
    #SBATCH --job-name=SingularityMPI      # nom du job
    #SBATCH --ntasks=40                    # Nombre total de processus MPI
    #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=SingularityMPI%j.out  # Nom du fichier de sortie
    #SBATCH --error=SingularityMPI%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 singularity
     
    # echo des commandes lancées
    set -x
     
    # exécution du code depuis l'espace d’exécution autorisé.
    # Selon l’implémentation de MPI installée dans le conteneur, on positionnera l'option --mpi=pmix_v2 ou --mpi=pmix_v3
    srun --mpi=pmix_v2 singularity exec $SINGULARITY_ALLOWED_DIR/my-container_CPU.sif ./exec_mpi
  • Soumettre ce script via la commande sbatch :
    $ sbatch singularity_mpi.slurm

Exécution d'un code GPU depuis une image Singularity en mode batch

Pour soumettre un travail GPU en batch sur Jean Zay, il faut :

  • Créer un script de soumission : voici un exemple pour la partition gpu par défaut (nœuds 4-GPU avec 40 cœurs physiques), enregistré dans le fichier singularity_gpu.slurm :
    singularity_gpu.slurm
    #!/bin/bash
    #SBATCH --job-name=SingularityGPU      # nom du job
    ##SBATCH --partition=gpu_p2            # de-commente pour la partition gpu_p2
    #SBATCH --ntasks=1                     # nombre total de taches (= nombre de GPU ici)
    #SBATCH --gres=gpu:1                   # nombre de GPU per nœud (1/4 des GPU)
    #SBATCH --cpus-per-task=10             # nombre de coeurs CPU par tache (1/4 du noeud 4-GPU)
    ##SBATCH --cpus-per-task=3             # nombre de coeurs CPU par tache (pour gpu_p2 : 1/8 du noeud 8-GPU)
    # /!\ Attention, "multithread" fait reference à l'hyperthreading dans la terminologie Slurm
    #SBATCH --hint=nomultithread           # hyperthreading desactive
    #SBATCH --time=00:10:00                # Temps d’exécution maximum demande (HH:MM:SS)
    #SBATCH --output=SingularityGPU%j.out  # Nom du fichier de sortie
    #SBATCH --error=SingularityGPU%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 singularity
     
    # echo des commandes lancées
    set -x
     
    # exécution du code depuis espace d’exécution autorisé avec l'option --nv afin de prendre en compte les cartes NVIDIA
    srun singularity exec --nv $SINGULARITY_ALLOWED_DIR/my-container_GPU.sif python ./my_model.py
  • Soumettre ce script via la commande sbatch :
    $ sbatch singularity_gpu.slurm

Remarques

  • L’exécution d'une image Singularity depuis une frontale est prohibée. Seuls les modes batch et interactif sont autorisés.
  • L'espace d’exécution autorisé $SINGULARITY_ALLOWED_DIR est limité à 20 conteneurs et non décompté dans les quotas utilisateurs.
  • La virtualisation de réseau de type ipvlan, macvlan, ptp, bridge, etc… n'est pas autorisée (nécessite d'être root). Le réseau du host est utilisé.
  • L’exécution de conteneur sous forme de SANDBOX n'est pas autorisée sur Jean Zay.
  • L’exécution de conteneur en mode fakeroot n'est pas autorisée sur Jean Zay.
  • Pour l'exécution d'un code parallèle MPI depuis une image Singularity, et selon l’implémentation de MPI installée dans le conteneur, on positionnera l'option --mpi=pmix_v2 ou --mpi=pmix_v3.
  • L’option --bind permet de monter des répertoires depuis le host vers le conteneur :
    --bind directory_host1:directory_container1,directory_host2:directory_container2, ...
  • Pour une exécution sur la partition gpu_p2, il faut spécifier --partition=gpu_p2 et --cpus-per-task=3.
  • Il n'est pour le moment pas possible de lancer Jupyter (Notebook ou Lab) et TensorBoard depuis un container Singularity.
  • Les ressources en mémoire RAM étant limités à 5GB par utilisateur sur les frontales, il est fortement recommandé d'utiliser les nœuds de pré/post-traitement pour la construction ou la convertion de conteneurs nécessitants des ressources importantes.

Tests de performance

Documentation