Chameleon mini-tutorial

Table of Contents

1. Environnement

Nous nous basons entièrement sur l'environnement de développement plafrim-formation & guix du devoir 1. Pour rappel, vous pouvez vérifier vos canaux avec guix describe --format=channels.

2. Mono-noeud

2.1. Réservation d'un noeud miriel

Nous allons ici réserver un noeud miriel en exclusif (--exclusive) (à utiliser avec parcimonie, pour les études de performance).

salloc -p miriel -N 1 --exclusive
ssh <node id>

Nous pouvons vérifier la topologie de la machine:

guix shell coreutils hwloc -- hwloc-ls

Combien de coeurs sont-ils vus par hwloc? Est-ce consistant avec la documentation plafrim?

Que voit starpu?

guix shell coreutils starpu -- starpu_machine_display

2.2. Produit de matrice (GEMM)

2.2.1. via votre code d'is328 alias mini-chameleon

On peut directement obtenir le code de base d'is328 (alias mini-chameleon), le compiler et exécuter un produit de matrice via:

guix shell --pure mini-chameleon openssh -- perf_dgemm -v seq

C'est bien sûr plus intéressant de faire de même avec votre propre code que vous aurez enrichi:

export HOME_IS328=/path/to/my/great/is328 # no '/' at the end
guix shell --pure mini-chameleon openssh --with-source=mini-chameleon=$HOME_IS328 -- perf_dgemm -v seq

Avec un gcc récent (gcc 11.2):

guix shell --pure mini-chameleon openssh --with-source=mini-chameleon=$HOME_IS328 --with-c-toolchain=mini-chameleon=gcc-toolchain -- perf_dgemm -v seq

Notez qu'il est possible d'entrer dans une session. Par exemple:

guix shell --pure mini-chameleon coreutils openssh --with-source=mini-chameleon=$HOME_IS328 # on entre dans la session
ls $GUIX_ENVIRONMENT/bin/ # ex: on affiche les binaires exécutables installés dans la session
exit # on quitte la session

Pour rappel, on peut tester le blas de l'environnement via l'option -v mkl (qui, contrairement à ce que son nom semble indiquer ne se limite donc pas à mkl). Ici on teste ainsi openblas puis mkl:

guix shell --pure mini-chameleon openssh -- perf_dgemm -v mkl # c'est bien openblas ici
guix shell --pure mini-chameleon openssh --with-input=openblas=mkl -- perf_dgemm -v mkl # et mkl là

On peut jouer avec les tailles de matrice (options -M, -N, -K) et également le nombre de threads utilisés via les variables d'environnement MKL_NUM_THREADS et OMP_NUM_THREADS.

2.2.2. via chameleon

Exécuter un produit de matrice:

guix shell --pure chameleon openssh -- chameleon_dtesting -H -o gemm --check

Pour obtenir de l'aide:

guix shell --pure coreutils openssh chameleon -- chameleon_dtesting -h

Exécuter un produit de matrice en choisissant les dimensions \(m=4000\), \(n=2000\) et \(k=1000\):

guix shell --pure coreutils openssh chameleon -- chameleon_dtesting -H -o gemm -m 4000 -n 2000 -k 1000 --check

Comment les workers starpu se sont-ils répartis le travail (voir On-line feedback):

STARPU_PROFILING=1 STARPU_WORKER_STATS=1 guix shell --pure --preserve=^STARPU coreutils openssh chameleon -- chameleon_dtesting -H -o gemm -m 4000 -n 2000 -k 1000 --check

Remplaçons openblas par mkl

guix shell --pure coreutils openssh chameleon --with-input=openblas=mkl -- chameleon_dtesting -H -o gemm -m 4000 -n 2000 -k 1000 --check

2.3. Factorisation QR via chameleon

2.3.1. Ressources

2.3.2. Exécution basique

guix shell --pure coreutils openssh chameleon -- chameleon_dtesting -H -o geqrf --check

2.3.3. Exécution avec un arbre de réduction

guix shell --pure coreutils openssh chameleon -- chameleon_dtesting -H --qra 4 -o geqrf --check

2.3.4. Dessiner (et observer les arbres de réduction)

On peut dessiner un arbre de réduction:

guix shell --pure coreutils openssh chameleon
$GUIX_ENVIRONMENT/bin/draw_hqr -M 16 -N 8 -a 4 ; inkscape hqr.qvg

Pour l'observer, rapatrier le fichier sur votre machine (ou connectez vous avec la transmission d'X sur plafrim) et utilisez inkscape (p. ex.):

guix shell --pure inkscape -- inkscape hqr.svg

Vous pouvez aussi retrouver le fichier généré ici (attention, utiliser plutôt inkscape que votre navigateur pour le visualiser).q

2.4. Libérer le noeud

squeue -u <username>
scancel <jobid>

3. Multi-noeuds

3.1. Réservation multi-noeuds

Dans l'exemple suivant, on fait une réservation exclusive sur deux noeuds.

salloc -p miriel -N 2 --exclusive

3.2. Dîtes "bonjour le monde"

La réservation précédente est prévue pour deux noeuds (-N 2) avec un processus par noeud (on pourrait autrement demander --ntasks-per-node=24, cf. the nomenclature slurm, auquel cas il y aurait 48 processus).

Voici trois façon de vérifier que les deux processus s'annoncent correctement en donnant leur hostname.

3.2.1. slurm système lance l'environnement guix

Ici nous utilisons le slurm du système (which srun) pour lancer l'environnement:

srun -l guix shell --pure inetutils -- hostname

3.2.2. slurm système depuis l'environnement guix

On peut alternativement, depuis un environnement guix, utiliser le slurm système en donnant son chemin en dur (/usr/bin/srun) et en préservant les variables d'environnement slurm (--preserve=^SLURM) qui ont été positionnées par salloc plus tôt:

guix shell --pure --preserve=^SLURM inetutils -- /usr/bin/srun -l hostname

3.2.3. slurm guix depuis l'environnement guix

Une troisième possibilité, sans doute la plus élégante, est d'utiliser le client slurm fourni par guix. Il faut s'assurer de fournir une version compatible avec le slurmd du système, en l'occurrence slurm@19, en sus de préserver les variables d'environnement slurm (--preserve=^SLURM):

guix shell --pure --preserve=^SLURM inetutils slurm@19 -- srun -l hostname

3.3. Vérifiez l'environnement srun sur chaque noeud

guix shell --pure --preserve=^SLURM coreutils openssh slurm@19 --with-input=slurm=slurm@19 -- srun -l env

3.4. Ping Pong

guix shell --pure --preserve=^SLURM intel-mpi-benchmarks openssh slurm@19 --with-input=slurm=slurm@19 -- srun -l IMB-MPI1 Pingpong

Notez que sur plafrim actuellement c'est la version 19 de slurm qui est déployée (srun --version). Par défaut, dans votre environnement guix, c'est la version 20 (guix shell --pure slurm -- srun --version). Il est donc préférable de demander explicitement un slurm@19 (--with-input=slurm=slurm@19).

3.5. Hello world MPI

On peut effectuer un petit "hello world" pour vérifier si on arrive à utiliser correctement mpi (notez qu'on évite d'utiliser =ucx via OMPI_MCA_pml='^ucx' puis --preserve="^OMPI" ) et si les processus parlent bien de là où ils sont sensés parler:

OMPI_MCA_pml='^ucx' guix shell --pure --preserve="^SLURM|^OMPI" slurm hello-mpi --with-input=slurm=slurm@19 -- srun -l hello-mpi

Notez qu'on peut également utiliser directement mpiexec. openmpi étant lié à slurm lors de se construction, il pourra accéder à la liste de noeuds réservées par slurm. Il faut toutefois lui préciser le nombre de processus qu'on souhaite lancer (-n 2) et le fait de les associer par noeud --map-by node):

OMPI_MCA_pml='^ucx' guix shell --pure --preserve="^SLURM|^OMPI" slurm hello-mpi --with-input=slurm=slurm@19 -- mpiexec --tag-output -n 2 --map-by node hello-mpi

À noter que si la réservation salloc a été faite en précisant explicitement le nombre de "tâches" slurm (via salloc -p miriel -N 2 -n 2 --exclusive dans notre cas), mpiexec n'a pas besoin de ces options supplémentaires:

OMPI_MCA_pml='^ucx' guix shell --pure --preserve="^SLURM|^OMPI" slurm hello-mpi --with-input=slurm=slurm@19 -- mpiexec --tag-output hello-mpi

3.6. Exemple de produit de matrice

3.6.1. via votre code (mini-chameleon)

On positionne le pointeur vers le source:

export HOME_IS328=/path/to/my/great/is328 # no '/' at the end

On peut jouer p. ex. avec la version starpu:

guix shell --pure --preserve="^OMPI|^SLURM|^STARPU" coreutils gdb mini-chameleon openmpi openssh slurm xterm --with-input=slurm=slurm@19 --with-source=mini-chameleon=$HOME_IS328 -- srun check_dgemm -v starpu   

Et on peut débugger avec gdb via xterm -e (il faut s'être connecté à plafrim avec l'option -Y d'ssh):

guix shell --pure --preserve="^OMPI|^SLURM|^STARPU" coreutils gdb mini-chameleon openmpi openssh slurm xterm --with-input=slurm=slurm@19 --with-debug-info=mini-chameleon --with-debug-info=starpu --with-source=mini-chameleon=$HOME_IS328 -- srun xterm -e gdb --args check_dgemm -v starpu

3.6.2. via chameleon

guix shell --pure --preserve=^SLURM chameleon openssh slurm --with-input=slurm=slurm@19 -- srun chameleon_dtesting -H -o gemm --check

Remplaçons openblas par mkl:

guix shell --pure --preserve=^SLURM chameleon openssh slurm --with-input=slurm=slurm@19 --with-input=openblas=mkl -- srun chameleon_dtesting -H -o gemm --check

Sans les erreurs ucx:

OMPI_MCA_pml='^ucx' guix shell --pure --preserve="^SLURM|^OMPI" chameleon openssh slurm --with-input=slurm=slurm@19 --with-input=openblas=mkl -- srun chameleon_dtesting -H -o gemm --check

3.7. Libérez les noeuds

squeue -u <username>
scancel <jobid>

4. Singularity

4.1. Création de l'image singularity

Nous pouvons créer une image singularity par exemple ainsi:

guix pack -f squashfs bash coreutils grep hello hello-mpi intel-mpi-benchmarks inetutils openssh sed slurm which --with-input=slurm=slurm@19 -S /bin=bin --entry-point=/bin/bash

4.2. Réservation multi-noeuds

Dans l'exemple suivant, on fait une réservation exclusive sur deux noeuds.

salloc -p miriel -N 2 --exclusive

4.3. Bonjour le monde

Il est possible d'utiliser srun sur une application non MPI telle que hostname:

srun -l singularity exec /gnu/store/f96nn7ck8pn9g3pmp83g4mhppzxlyqx7-bash-coreutils-grep-hello-hello-mpi-squashfs-pack.gz.squashfs hostname

4.4. Hello World MPI

En revanche, pour tourner une application mpi, il faut charger explicitement le module mpi correspondant à la version utilisée dans l'image. Celui sera utilisé pour que le lanceur mpiexec, à l'extérieur de l'image singularity soit compatible avec le binaire (ici hello-mpi) qui lui-même a été lié à mpi lors de la construction de l'image:

module load mpi/openmpi/4.1.1
OMPI_MCA_pml='^ucx' mpiexec -n 2 --map-by node singularity exec /gnu/store/f96nn7ck8pn9g3pmp83g4mhppzxlyqx7-bash-coreutils-grep-hello-hello-mpi-squashfs-pack.gz.squashfs  hello-mpi

4.5. Libérez les noeuds

squeue -u <username>
scancel <jobid>

4.6. Hello World MPI via son propre MPI hôte

4.6.1. Installation d'OpenMPI

export OMPI_DIR=/path/to/openmpi/install/dir/
mkdir -p $OMPI_DIR
guix build -S openmpi
tar xJf /gnu/store/47hmvcd4qpn2f799lp6r4iq2yxxkxxp6-openmpi-4.1.1.tar.xz
./configure --with-slurm --prefix=$OMPI_DIR
srun -N 1 -p miriel --exclusive make -j all install

4.6.2. Test de l'installation

export PATH=$OMPI_DIR/bin:$PATH
mpiexec -n 2 --map-by node hostname

Remarquez les instructions recommandées mais pas nécessaire en pratique:

export MANPATH=$OMPI_DIR/share/man:$MANPATH
export LD_LIBRARY_PATH=$OMPI_DIR/lib:$LD_LIBRARY_PATH

4.6.3. Réservation multi-noeuds

On fait une réservation sur deux noeuds:

salloc -p miriel -N 2 --exclusive

4.6.4. Hello World MPI

OMPI_MCA_pml='^ucx' mpiexec -n 2 --map-by node singularity exec /gnu/store/f96nn7ck8pn9g3pmp83g4mhppzxlyqx7-bash-coreutils-grep-hello-hello-mpi-squashfs-pack.gz.squashfs hello-mpi

4.6.5. Libérez les noeuds

squeue -u <username>
scancel <jobid>

5. Tester un autre MPI (nmad)

5.1. Réservation multi-noeuds

salloc -p miriel -N 2 --exclusive

5.2. Hello World MPI

Dans le cas d'nmad, mpiexec (fourni donc par nmad) appelle in fine srun (en lui transmettant les bonnes options). On peut donc faire l'appel ainsi:

guix shell --pure --preserve="^SLURM" slurm hello-mpi --with-input=slurm=slurm@19 --with-input=openmpi=nmad -- mpiexec hello-mpi

Il est à noter que l'nmad fourni par guix n'est pas lui-même linké avec slurm et on peut donc se passer de --with-input=slurm=slurm@19 (du moment qu'on charge slurm@19):

guix shell --pure --preserve="^SLURM" hello-mpi openmpi slurm@19 --with-input=openmpi=nmad -- mpiexec hello-mpi

Notez qu'on aurait pu mettre explicitement nmad à la place d'openmpi du fait de la transformation --with-input=openmpi=nmad.

5.3. Produit de matrice

Dans le cas d'nmad, mpiexec (fourni donc par nmad) appelle in fine srun (en lui transmettant les bonnes options). On peut donc faire l'appel ainsi:

guix shell --pure --preserve="^SLURM" chameleon openmpi slurm --with-input=slurm=slurm@19 --with-input=openmpi=nmad --with-input=openblas=mkl -- mpiexec chameleon_dtesting -H -o gemm --check

Comme ci-dessus, puisqu'nmad fourni par guix n'est pas lui-même linké avec slurm, on peut se passer de --with-input=slurm=slurm@19 (du moment qu'on charge slurm@19):

guix shell --pure --preserve="^SLURM" chameleon openmpi slurm@19 --with-input=openmpi=nmad --with-input=openblas=mkl -- mpiexec chameleon_dtesting -H -o gemm  --check 

5.4. Libérez les noeuds

squeue -u <username>
scancel <jobid>

Author: E. Agullo & M. Faverge

Created: 2022-01-07 Fri 10:36

Validate