3 — Déployer avec Guix sans Guix

Table of content
  • Ce tutoriel utilise la plateforme PlaFRIM pour construire des conteneurs avec Guix. À titre d’exemple, un conteneur sera déployé en utilisant la commande singularity.

  • Les conteneurs peuvent être construits sur n’importe quelle machine où Guix est installé. Pour l’installation de Guix sur une distribution Linux, se référer à la documentation. Attention, une image de conteneur construite ailleurs que sur PlaFRIM devra ensuite être copiée sur PlaFRIM pour pouvoir être utilisée.

  • Des instructions ainsi que des démonstrations enregistrées sont fournies pour différents supercalculateurs nationaux et européens. Elles peuvent être facilement adaptées à d’autres supercalculateurs.

  • L’application choisie est Chameleon, utilisée dans la partie précédente.

Présentation de guix pack

Extrait du manuel de Guix :

La commande guix pack crée […] une archive […] contenant les binaires pour le logiciel qui vous intéresse ainsi que ses dépendances. […]

Syntaxe générale

guix pack [options] <logiciel1> [<logiciel2> ...]

ou

guix pack [options] -m <fichier_manifeste>

Formats d’archive

L’archive peut être générée sous différents formats grâce à l’option --format/-f :

  • tarball : C’est le format par défaut. Il produit une archive tar contenant tous les binaires et les liens symboliques spécifiés.
  • docker : Cela produit une archive tar qui suit la spécification des images Docker.
  • squashfs : Cela produit une image SquashFS compatible avec Singularity.

Elle permet de mettre en place des liens symboliques dans l’archive générée.

Par exemple, pour créer un lien symbolique vers /bin placé à la racine de l’archive :

# Création d'une archive tar.gz contenant le paquet hello avec un
# lien symbolique du répertoire `/bin` vers `bin` à la racine de
# l'archive.
guix pack -S /bin=bin hello
# [...]
# building /gnu/store/ahkhxpcdk354l8b5wg1d2dgnfxch0gf9-hello-tarball-pack.tar.gz.drv...
# /gnu/store/p8ibfzlw34vinwjmcmjpal4mbmzz5qp5-hello-tarball-pack.tar.gz
tar --exclude='./*/*/*' -tvf /gnu/store/p8ibfzlw34vinwjmcmjpal4mbmzz5qp5-hello-tarball-pack.tar.gz
# drwxr-xr-x root/root         0 1970-01-01 01:00 ./
# lrwxrwxrwx root/root         0 1970-01-01 01:00 ./bin -> gnu/store/41cjkjwl1kznvqv5q2r7xigzzw3dkswg-profile/bin
# drwxr-xr-x root/root         0 1970-01-01 01:00 ./gnu/
# drwxrwxr-t root/root         0 1970-01-01 01:00 ./gnu/store/
#
#
# Sans création de lien symbolique :
guix pack hello
# [...]
# building /gnu/store/fbhql2v2p7cd77n22c4xzsijgh164xjd-hello-tarball-pack.tar.gz.drv...
# /gnu/store/sjhla9zw68fjd0sdhvwxal6c1d83f8zh-hello-tarball-pack.tar.gz
tar --exclude='./*/*/*' -tvf /gnu/store/sjhla9zw68fjd0sdhvwxal6c1d83f8zh-hello-tarball-pack.tar.gz
# drwxr-xr-x root/root         0 1970-01-01 01:00 ./
# drwxr-xr-x root/root         0 1970-01-01 01:00 ./gnu/
# drwxrwxr-t root/root         0 1970-01-01 01:00 ./gnu/store/

Option -C/--compression

Elle permet de spécifier le format de compression de l’archive générée :

# Compression avec gzip (défaut)
guix pack hello # équivalent à guix pack -C gzip hello
# Compression avec xz
guix pack -C xz hello
# Compression avec zstd
guix pack -C zstd hello

Option -r/--root

Elle permet de créer un lien symbolique vers l’archive créée dans le répertoire /gnu/store :

guix pack hello -r hello-link
# [...]
# building /gnu/store/fbhql2v2p7cd77n22c4xzsijgh164xjd-hello-tarball-pack.tar.gz.drv...
# /gnu/store/sjhla9zw68fjd0sdhvwxal6c1d83f8zh-hello-tarball-pack.tar.gz
ls -l hello-link
# hello-link ⇒ /gnu/store/sjhla9zw68fjd0sdhvwxal6c1d83f8zh-hello-tarball-pack.tar.gz

Option -R/--relocatable

Elle permet de générer une archive contenant des binaires relocalisables/repositionnables (relocatable binaries), des binaires que l’on peut placer n’importe où dans l’arborescence du système de fichiers et les lancer à partir de là (ils trouveront automatiquement les bibliothèques partagées auxquelles ils sont liés).

Pour fonctionner, les binaires générés nécessitent le support des “espaces de nom utilisateurs” (user namespaces) dans le noyau Linux.

# Génération d'une archive contenant des binaires relocalisables
# compressée avec zstd
guix pack -R -C zstd hello

Utilisation de Singularity sur PlaFRIM

Construction d’une image Singularity avec Guix

  • Construction de l’image de conteneur Singularity avec la commande pack de Guix, prefixée de la commande time-machine.
guix time-machine -C channels.scm \
  -- pack -f squashfs --with-input=cuda-toolkit=cuda-toolkit@11 \
          -r ./chameleon-cuda.sif chameleon-cuda-mkl-mt bash
# [...]
# building /gnu/store/ppxr1hz739cw0hzr03swac8d7r6qkclb-chameleon-cuda-mkl-mt-bash-squashfs-pack.gz.squashfs.drv...
# /gnu/store/wqnjzy0879dqnncqqx05s3br2vivjrk2-chameleon-cuda-mkl-mt-bash-squashfs-pack.gz.squashfs
Tip

Les machines utilisées pour ce tutoriel possèdent des GPU NVIDIA K40 qui ne sont plus supportés par CUDA-12 (la version par défaut de CUDA). Il faut donc utiliser une option de transformation pour recompiler chameleon-cuda avec CUDA-11 qui supporte encore les GPU K40.

Tip

Singularity requiert la présence de /bin/sh dans l’image, c’est pour cela qu’il faut toujours ajouter le paquet bash (ou un autre shell) dans la liste des paquets.

En cas d’absence, les commandes singularity run et singularity exec échoueront avec un message de type no such file or directory.

Tip

La commande guix time-machine permet d’utiliser le fichier channels.scm précédemment téléchargé. C’est une des méthodes permettant la reproducibilité bit à bit de l’image construite.

Déploiment du conteneur

  • Exécution de Chameleon dans le conteneur Singularity à travers une session SLUM interactive.
export HFI_NO_CPUAFFINITY=1
srun --mpi=pmi2 -C sirocco -N 1 --exclusive -x sirocco03 \
     singularity exec --nv chameleon-cuda.sif \
     bash -c "LD_PRELOAD=/.singularity.d/libs/libcuda.so chameleon_dtesting -o gemm -n 20000 -b 960 -P 1 -l 1 -g 2"
# [...]
# Id;Function;threads;gpus;P;Q;mtxfmt;nb;transA;transB;m;n;k;lda;ldb;ldc;alpha;beta;seedA;seedB;seedC;tsub;time;gflops
# 0;sgemm;17;2;1;1;0;960;111;111;20000;20000;20000;20000;20000;20000;4.892778e-01;-1.846424e-01;1649760492;596516649;1189641421;0.000000e+00;8.709111e+00;1.837157e+03
Tip

Le déploiement d’une application CUDA construite par Guix nécessite le positionnement de la variable LD_PRELOAD avec le chemin absolu vers le fichier libcuda.so car il est fourni par le pilote CUDA propriétaire installé sur la machine et ne fait pas partie de la pile logicielle générée par Guix.

Tip

Les variables d’environnement sont propagées dans le conteneur Singularity.

Tip

L’option --nv passée à singularity exec permet de rendre accessible libcuda.so à l’intérieur du conteneur.

Tip

L’option --mpi passée à srun permet de spécifier la bibliothèque utilisée pour communiquer avec la couche Open MPI contenue dans l’image Singularity.

Info

L’installation Singularity sur PlaFRIM Formation ne semble pas supporter la communication inter-nœuds avec Open MPI.

Utilisation de binaires repositionnables sur PlaFRIM

Construction de l’archive

guix time-machine -C channels.scm \
  -- pack -R -S /bin=bin -C xz \
          --with-input=cuda-toolkit=cuda-toolkit@11 \
          -r chameleon-cuda-mkl.tar.xz \
          chameleon-cuda-mkl-mt
# [...]
# building /gnu/store/n3n628wkpgfx8xd4cdhl69z8dc2700sd-chameleon-cuda-mkl-mt-tarball-pack.tar.xz.drv...
# /gnu/store/h9p1cpjcbhd75w1s2sf5gpcarik9xb4k-chameleon-cuda-mkl-mt-tarball-pack.tar.xz

Déploiement de l’archive

  • Extraction de l’archive dans un répertoire préalablement créé
mkdir chameleon-cuda-mkl && tar xf chameleon-cuda-mkl.tar.xz -C chameleon-cuda-mkl
  • Exécution de Chameleon avec srun sur 2 nœuds CPU :
export HFI_NO_CPUAFFINITY=1
srun -C miriel --exclusive --nodes=2 \
     ./chameleon-cuda-mkl/bin/chameleon_dtesting \
     -o gemm -n 20000 -b 960 -P 2 -l 1 --nowarmup
# [...]
# Id;Function;threads;gpus;P;Q;mtxfmt;nb;transA;transB;m;n;k;lda;ldb;ldc;alpha;beta;seedA;seedB;seedC;tsub;time;gflops
# 0;dgemm;23;0;2;1;0;960;111;111;20000;20000;20000;20000;20000;20000;-1.935109e-01;3.817601e-01;1681692777;1714636915;1957747793;0.000000e+00;1.337962e+01;1.195849e+03
  • Exécution de Chameleon avec srun sur un nœud GPU :
export HFI_NO_CPUAFFINITY=1
srun -C sirocco -x sirocco03 --exclusive --nodes=1 \
     env LD_PRELOAD=/usr/lib64/libcuda.so ./chameleon-cuda-mkl/bin/chameleon_dtesting \
     -o gemm -n 20000 -b 960 -P 1 -l 1 -g 2 --nowarmup
# [...]
# Id;Function;threads;gpus;P;Q;mtxfmt;nb;transA;transB;m;n;k;lda;ldb;ldc;alpha;beta;seedA;seedB;seedC;tsub;time;gflops
# 0;dgemm;17;2;1;1;0;960;111;111;20000;20000;20000;20000;20000;20000;-1.935109e-01;3.817601e-01;1681692777;1714636915;1957747793;0.000000e+00;8.309933e+00;1.925407e+03
  • Exécution de Chameleon avec srun sur 2 nœuds GPU :
export HFI_NO_CPUAFFINITY=1
srun -C sirocco -x sirocco03 --exclusive --nodes=2 \
     env LD_PRELOAD=/usr/lib64/libcuda.so ./chameleon-cuda-mkl/bin/chameleon_dtesting \
     -o gemm -n 20000 -b 960 -P 2 -l 1 -g 4 --nowarmup
# [...]
# Id;Function;threads;gpus;P;Q;mtxfmt;nb;transA;transB;m;n;k;lda;ldb;ldc;alpha;beta;seedA;seedB;seedC;tsub;time;gflops
# 0;dgemm;19;4;2;1;0;960;111;111;20000;20000;20000;20000;20000;20000;-1.935109e-01;3.817601e-01;1681692777;1714636915;1957747793;0.000000e+00;5.438546e+00;2.941963e+03
  • Questions
    • Quelles sont les commandes à effectuer pour exécuter la version de Chameleon avec support CUDA et OpenBLAS à la place de MKL (paquet chameleon-cuda) ?
    • Quelle est l’influence de la variable d’environnement OPENBLAS_NUM_THREADS=1 ?

Déploiement sur les supercalculateurs français et européens

Warning

Les exemples suivants nécessitent un accès à des machines spécifiques qui n’est pas fourni dans le cadre de ce tutoriel.

Ces exemples sont accompagnées de démonstrations enregistrées appliquant les commandes proposées.

Construction d’une image Singularity pour GPU NVIDIA

Pour les déploiements suivants, une image contenant Chameleon avec le support de CUDA en version 12 (par défaut) et MKL sera utilisée afin de pouvoir utiliser le matériel plus récent des machines ciblées.

guix time-machine -C channels.scm \
  -- pack -f squashfs -r ./chameleon-cuda-mkl.sif \
          chameleon-cuda-mkl-mt bash
# [...]
# /gnu/store/bmil8b5gn9pf618mm7bmlbqs448lxi1i-chameleon-cuda-mkl-mt-bash-squashfs-pack.gz.squashfs

Déploiement de l’image Singularity sur Jean-Zay

Jean-Zay est un supercalculateur français qui possède des GPU NVIDIA V100 et qui fournit l’outil de déploiement Singularity.

  • Copie de l’image sur Jean-Zay
scp chameleon-cuda-mkl.sif user@jean-zay.idris.fr:chameleon-cuda-mkl.sif
  • Connexion à Jean-Zay
ssh jean-zay
  • Mise en place de l’environnement d’exécution sur Jean-Zay

L’image doit être copiée dans l’espace autorisé ($SINGULARITY_ALLOWED_DIR) pour être accessible à Singularity (cette étape est spécifique à Jean-Zay, plus de détails dans la documentation).

Il faut ensuite charger le module singularity (cette étape n’est pas toujours nécessaire mais elle l’est sur Jean-Zay).

idrcontmgr cp chameleon-cuda-mkl.sif
module load singularity
  • Exécution de Chameleon en mode interactif avec SLURM et Singularity (adapter account)
srun -A account@v100 --time=0:10:00 --nodes=1 --cpu-bind=socket --exclusive \
     --hint=nomultithread --gres=gpu:4 --mpi=pmi2 \
     singularity exec --nv $SINGULARITY_ALLOWED_DIR/chameleon-cuda-mkl.sif \
     bash -c \
     "LD_PRELOAD=/.singularity.d/libs/libcuda.so chameleon_dtesting -o gemm -n 20000 -b 960 -l 1 -P 1 -g 4 --nowarmup"
# [...]
# Id;Function;threads;gpus;P;Q;mtxfmt;nb;transA;transB;m;n;k;lda;ldb;ldc;alpha;beta;seedA;seedB;seedC;tsub;time;gflops
# 0;dgemm;15;4;1;1;0;960;111;111;20000;20000;20000;20000;20000;20000;-1.935109e-01;3.817601e-01;1681692777;1714636915;1957747793;0.000000e+00;2.288457e+00;6.991611e+03
  • Exemple vidéo

Déploiement du conteneur sur Vega (EuroHPC)

Vega est un supercalculateur européen (EuroHPC) qui possède des GPU NVIDIA A100 et qui fournit l’outil de déploiement Singularity.

  • Copie de l’image sur Vega (adapter selon sa configuration SSH)
scp chameleon-cuda-mkl.sif vega:chameleon-cuda-mkl.sif
  • Connexion à Vega (à adapter en fonction de sa configuration SSH)
ssh vega
  • Exécution de Chameleon en mode interactif avec SLURM et Singularity
srun --exclusive --partition=gpu --gres=gpu:4 -N 2 --mpi=pmi2 \
     singularity exec --bind /tmp:/tmp chameleon-cuda.sif \
     bash -c "LD_PRELOAD=/.singularity.d/libs/libcuda.so chameleon_dtesting -o gemm -n 20000 -b 960 --nowarmup -g 4"
  • Exemple vidéo

Déploiement du conteneur sur MeluXina (EuroHPC)

MeluXina est un supercalculateur européen (EuroHPC) qui possède des GPU NVIDIA A100 et qui fournit l’outil de déploiement Singularity.

  • Copie de l’image sur MeluXina
scp chameleon-cuda-mkl.sif meluxina:chameleon-cuda-mkl.sif
  • Connexion à MeluXina
ssh meluxina
  • Lancement d’une console interactive sur un nœud de calcul avec SLURM (adapter project_id)
srun --pty -A project_id --partition=gpu -N 1 --exclusive --gpus-per-task=4 \
     --time=00:10:00 --qos=test bash
  • Chargement du module Singularity sur le noœud de calcul
module load Apptainer/1.3.6-GCCcore-13.3.0
Tip

Sur MeluXina, la commande singularity est disponible dans un module et la commande module est accessible seulement sur les nœuds de calcul.

  • Exécution de Chameleon avec Singularity
singularity exec --nv --bind /tmp:/tmp chameleon-cuda-mkl.sif \
            bash -c \
            'LD_PRELOAD=/.singularity.d/libs/libcuda.so chameleon_dtesting -o gemm -n 20000 -b 960 --nowarmup -g 4'
  • Exemple vidéo
Info

Cet exemple présente une utilisation mono-nœud. Pour un calcul sur plusieurs nœuds, l’utilisation d’un script avec sbatch est nécessaire.

Construction d’une image Docker pour GPU NVIDIA

Il est aussi possible de construire une image Docker pour ensuite la déployer avec Docker ou un outil de déploiement qui utilise des images Docker.

La commande suivante construit une image contenant la même pile logicielle que celle déployée avec Singularity dans les exemples précédents :

guix time-machine -C channels.scm \
  -- pack -f docker -r ./chameleon-cuda-mkl.tar.gz \
          chameleon-cuda-mkl-mt bash
# [...]
# /gnu/store/x5c9njin7x47nsrk1vkiqwb6nw4jsh03-chameleon-cuda-mkl-mt-bash-docker-pack.tar.gz

Déploiement de l’image Docker sur Joliot-Curie (TGCC)

Joliot-Curie est un supercalculateur français qui possède des GPU NVIDIA V100. L’exemple suivant propose de mettre en œuvre le déploiement d’une image Docker sur la partition Irène.

Ce supercalculateur nécessite l’utilisation d’outil spécifiques pour l’allocation des ressources (ccc_mprun, voir la documentation) et le déploiement de conteneurs (pcocc-rs, voir la documentation)

  • Copie de l’image sur Irène
scp chameleon-cuda-mkl.tar.gz irene:chameleon-cuda-mkl.tar.gz
  • Connexion à Irène
ssh irene
  • Import de l’image avec pcocc-rs.
pcocc-rs image import docker-archive:chameleon-cuda-mkl.tar.gz chameleon-cuda-mkl
  • Exécution de Chameleon en mode interactif avec les outils spécifiques du TGCC (adapter user_account)
ccc_mprun -p v100 -N 4 -n 4 -c 40 -E '--mpi=pmi2' -E '--ctr-module nvidia' \
  -m work,scratch -A user_account -T 600 -C chameleon-cuda-mkl \
  -- bash -c "LD_PRELOAD=/pcocc/nvidia/usr/lib64/libcuda.so chameleon_dtesting -o gemm -n 20000 -b 960 --nowarmup -g 4"
Tip

Sur Irène, le nombre de GPU alloués sur un nœud est lié au nombre de cœurs CPU alloués sur ce nœud. Ici, 20 cœurs sont alloués sur les 40 que contient un nœud V100, donc 50% des GPU disponibles sur le nœud sont alloués, soit 2 GPU sur 4. Voir la documentation pour plus de détails.

Tip

L’option --module nvidia permet de rendre accessible les bibliothèques CUDA dans le répertoire /pcocc/nvidia/usr/lib64 du conteneur.

  • Exemple vidéo

Construction d’une image Singularity pour GPU AMD

guix time-machine -C channels.scm \
  -- pack -f squashfs chameleon-hip-mkl-mt bash -r ./chameleon-hip-mkl.sif
# [...]
# /gnu/store/f1qr7h88dd85pnxsavcgpi4vmv3pgyxp-chameleon-hip-mkl-mt-bash-squashfs-pack.gz.squashfs

Déploiement sur LUMI

LUMI est un supercalculateur français qui possède des GPU AMD MI250 et qui fournit l’outil de déploiement Singularity.

  • Copie de l’image Singularity
scp chameleon-hip-mkl.sif lumi:chameleon-hip-mkl.sif
  • Connexion à LUMI
ssh lumi
  • Exécution de Chameleon avec SLURM en mode interactif (adapter project_id) sur un seul nœud
export MKL_NUM_THREADS=1
srun --cpu-bind=socket -A project_id --threads-per-core=1 --cpus-per-task=56 \
     --ntasks-per-node=1 -N 1 --time=00:05:00 --partition=dev-g --mpi=pmi2 \
     --gpus-per-node=8 \
     singularity exec --rocm --bind /sys chameleon-hip-mkl.sif \
     chameleon_dtesting -o gemm -n 20000 -b 960 -P 1 -l 1 --nowarmup -g 8
# [...]
# Id;Function;threads;gpus;P;Q;mtxfmt;nb;transA;transB;m;n;k;lda;ldb;ldc;alpha;beta;seedA;seedB;seedC;tsub;time;gflops
# 0;dgemm;47;8;1;1;0;960;111;111;20000;20000;20000;20000;20000;20000;-1.935109e-01;3.817601e-01;1681692777;1714636915;1957747793;0.000000e+00;1.512306e+00;1.057987e+04
Tip

D’après la documentation de Singularity, le support des GPU AMD nécessite l’option --rocm.

Tip

Le positionnement de la variable MKL_NUM_THREADS à la valeur 1 permet de désactiver le multi-threading de la bibliothèque MKL afin d’améliorer les performances.

  • Exemple vidéo