Jobs sur noeuds GPU

Les noeuds GPU sur les clusters GRICAD

Pour les simulations nécessitant des cartes GPU pour s’exécuter, plusieurs noeuds vous sont accessibles :

  • Le cluster Froggy dispose de 9 noeuds avec deux GPUS Kepler K20m. Ces noeuds sont appelés frogkepler.

  • Le cluster Bigfoot, dédié au calcul sur GPU, avec des noeuds de 4 GPUs NVIDIA Tesla V100 NVLink, des noeuds avec 2 NVIDIA A100 et des noeuds Virgo accessibles la nuit avec des GPU T4.

Utiliser le cluster Bigfoot

Le cluster “Bigfoot” est dédié aux calculs nécessitant l’usage de noeuds délivrant de la puissance de calcul par le biais de co-processeurs, actuellement des GPGPU. L’accès se fait de manière classique, depuis les bastions SSH de Gricad, vers la frontale bigfoot:

login@trinity:~$ ssh bigfoot
Linux bigfoot 4.19.0-18-amd64 #1 SMP Debian 4.19.208-1 (2021-09-29) x86_64
                       Welcome to Bigfoot cluster! 

                             :            :
                            .'            :
                        _.-"              :
                    _.-"                  '.
    ..__...____...-"                       :
   : \_\                                    :
   :    .--"                                 :
   `.__/  .-" _                               :
      /  /  ," ,-                            .'
     (_)(`,(_,'L_,_____       ____....__   _.'
      "' "             """""""          """   

GPU, GPU, GPU, ... ;-)

            Type 'chandler' to get cluster status  
          Type 'recap.py' to get cluster properties

Sample OAR submissions: 
  # Get a A100 GPU and all associated cpu and memory resources:
  oarsub -l /nodes=1/gpu=1 --project test -p "gpumodel='A100'" "nvidia-smi -L"
  # Get a MIG partition of an A100 on a devel node, to make some tests
  oarsub -l /nodes=1/gpu=1/migdevice=1 --project test -t devel "nvidia-smi -L"

Last login: Mon Jan 10 17:37:43 2022 from 129.88.178.43
login@bigfoot:~$ 

La commande chandler permet d’avoir un aperçu des ressources disponibles et de leur état instantané.

Plusieurs modèles de GPU sont disponibles. La commande recap.py donne des informations à jour sur la configuration matérielle des différents noeuds, en particulier le modèle et le nombre de GPU disponible à l’intérieur des noeuds:

login@bigfoot:~$ recap.py 
 ================================================================================
|   node  | cpumodel       | gpumodel  | gpus | cpus | cores| mem | mem/gpu |MIG|
 ================================================================================
|bigfoot1 | intel Gold 6130| V100      |   4  |   2  |   32 | 192 |   96  |  NO |
|    [ + 1  more node(s) ]                                                      |
|bigfoot3 | intel Gold 6130| V100      |   4  |   2  |   32 | 192 |   96  |  NO |
|bigfoot4 | intelGold 5218R| V100      |   4  |   2  |   40 | 192 |   96  |  NO |
|    [ + 1  more node(s) ]                                                      |
|bigfoot6 | intelGold 5218R| V100      |   4  |   2  |   40 | 192 |   96  |  NO |
|bigfoot7 | amd   EPYC 7452| A100      |   2  |   2  |   64 | 192 |   96  | YES |
|bigfoot8 | intelGold 5218R| V100      |   4  |   2  |   40 | 192 |   48  |  NO |
|bigfoot9 | amd   EPYC 7452| A100      |   2  |   2  |   64 | 192 |   96  |  NO |
|    [ + 2  more node(s) ]                                                      |
|bigfoot12| amd   EPYC 7452| A100      |   2  |   2  |   64 | 192 |   96  |  NO |
|virgo1   | intel      vcpu| T4        |   1  |   1  |    2 |   4 |    4  |  NO |
|    [ + 33 more node(s) ]                                                      |
|virgo35  | intel      vcpu| T4        |   1  |   1  |    2 |   4 |    4  |  NO |
 ================================================================================
 # of GPUS: 10 A100, 28 V100, 35 T4
login@bigfoot:~$ 

Les noeuds, hors noeuds Virgo T4, sont interconnectés via le même réseau à faible latence Omnipath que le cluster Dahu.

Les noeuds Virgo sont des noeuds utilisés pour l’enseignement en journée (un noeud reste disponible pour des tests) mais qui peuvent être utilisés pour des jobs la nuit.

Les espaces de stockage habituels sont disponibles depuis la frontale et tous les noeuds:

  • /home : un espace dédié au cluster Bigfoot, pour bien distinguer les environnements
  • /bettik : espace de travail capacitif à haute performance, partagé avec les clusters Dahu et Luke
  • /silenus : scratch temporaire à ultra haute performance (SSD/NVMe), partagé avec le cluster Dahu
  • Mantis : espace de stockage de type cloud géré sous iRods

Environnement logiciel

Les environnements classiques NIX et GUIX sont disponibles et partagés avec les clusters Dahu et Luke, ainsi que le répertoire d’applications spécifique /applis.

Pour installer les librairies couramment utilisées dans le calcul sur GPU, vous pouvez utiliser les environnements conda prédéfinis.

Pour utiliser les GPUs NVIDIA, il faudra également sourcer le toolkit CUDA adéquat. Vous pouvez utiliser le script suivant en passant le nom du cluster et la version du toolkit souhaitée. Exemple pour le toolkit version 11.7:

user@bigfoot:~$ source /applis/environments/cuda_env.sh 11.7

Pour lister les toolkits disponibles sur un cluster utilisez le script cuda_env.sh.

user@bigfoot:~$ source /applis/environments/cuda_env.sh -l

Lancement des jobs

Pour lancer un job, nous utilisons le gestionnaire de ressources OAR (dont les commandes essentielles sont décrites dans cette page.), et plus particulièrement la commande oarsub.

La particularité sur le cluster Bigfoot, est que l’unité de ressource à demander est généralement une gpu. Les autres ressources des noeuds de calcul (cpu-core et mémoire) ont été réparties et associées aux gpu en fonction de la configuration matérielle des noeuds qui est hétérogène.

Il est conseillé (mais pas obligatoire) de préciser le modèle de GPU que vous souhaitez obtenir sur vos noeuds de calcul, en exploitant la propriété OAR gpumodel.

L’exemple suivant donne les options minimales permettant de soumettre un job nécessitant une seule gpu sur un noeud qui dispose de GPU Nvidia A100:

oarsub -l /nodes=1/gpu=1 -p "gpumodel='A100'" ...

OAR allouera également au prorata, un certain nombre de coeurs de calcul généralistes (cpu-cores) et un certain volume de mémoire.

Cet autre exemple de job obtiendra 2 GPU Nvidia A100 sur le même noeud, ainsi que les ressources cpu et mémoire associées:

oarsub -l /nodes=1/gpu=2 -p "gpumodel='A100'" ...

OAR alloue les unités GPU en fonction de la propriété gpudevice. Pour connaître quelles sont les unités allouées, il faut utiliser, une fois sur le noeud (en interactif) la commande oarprint :

user@bigfoot2:~$ oarprint gpudevice
1
0

Cette même commande vous permet aussi de connaitre les cpu-cores associées aux gpudevice:

user@bigfoot8:~$ oarprint -P gpudevice,cpuset core
0 3
1 12
1 18
0 9
0 1
1 17
1 14
0 5
1 10
1 16
0 8
0 4
0 6
1 15
0 7
1 11
0 2
1 13
0 0
1 19

Ici, on a obtenu 20 coeurs de calcul et 2 GPU, chaque GPU étant associée à 10 coeurs dont on a listé le rang au sein du noeud de calcul.

Pour connaitre le montant de mémoire centrale alloué, on peut interroger le cgroup du job de la manière suivante:

user@bigfoot8:~$ cat /dev/oar_cgroups_links/memory/`cat /proc/self/cpuset`/memory.limit_in_bytes
100693262336

Ce montant de mémoire varie en fonction du nombre de GPU obtenues sur le noeud et en fonction des caractéristiques du noeud. La propriete mem_per_gpu (en Go) permet de connaitre la configuration des noeuds et de mettre des contraintes à la soumission des jobs sur la quantité de mémoire centrale nécessaire au job. Par exemple:

oarsub -l /nodes=1/gpu=2 -p "gpumodel='A100' and mem_per_gpu > 64"...

Pour les GPU Nvidia, la commande nvidia-smi permet d’obtenir des informations sur les GPU accessibles. Elle permet d’ailleurs de voir que OAR ne permettera d’accéder qu’aux GPU qui ont été allouées:

user@bigfoot:~$ oarsub -l /nodes=1/gpu=2 -p "gpumodel='V100'" --project test -I
[ADMISSION RULE] Set default walltime to 7200.
[ADMISSION RULE] Modify resource description with type constraints
OAR_JOB_ID=293
Interactive mode: waiting...
Starting...
Connect to OAR job 293 via the node bigfoot8
user@bigfoot8:~$ nvidia-smi -L
GPU 0: Tesla V100-SXM2-32GB (UUID: GPU-263f55be-a11c-81be-8af6-e948471cb954)
GPU 1: Tesla V100-SXM2-32GB (UUID: GPU-9e4e2b6c-19ea-73ef-7026-00619f988787)
bzizou@bigfoot8:~$ logout
Connection to bigfoot8 closed.
Disconnected from OAR job 293.
user@bigfoot:~$ oarsub -l /nodes=1/gpu=1 -p "gpumodel='A100'" --project test -I
[ADMISSION RULE] Set default walltime to 7200.
[ADMISSION RULE] Modify resource description with type constraints
OAR_JOB_ID=294
Interactive mode: waiting...
Starting...
Connect to OAR job 294 via the node bigfoot12
user@bigfoot12:~$ nvidia-smi -L
GPU 0: NVIDIA A100-PCIE-40GB (UUID: GPU-45d882aa-be45-3db7-bd3a-06da9fcaf3b1)
user@bigfoot12:~$ logout

Limitations

Le walltime maximum est de 48h. Cela est necessaire afin de permettre un turnover raisonnable pour un partage équitable des ressources. C’est aussi nécessaire pour faciliter les opérations de maintenance et de mise à jour de la machine. Si vos jobs nécessitent un temps d’éxécution plus long, vous devez alors mettre en place ou utiliser des fonctionnalités de checkpoint au sein de vos applications (c’est à dire que vos applications doivent pouvoir sauver leur état dans des fichiers afin de pouvoir redémarrer plus tard sur un cet état en chargeant ces fichiers).

Soumettre un job à l’aide d’un script de soumission

La soumission d’un job CPU à l’aide d’un script est expliquée sur cette page.

La soumission d’un job GPU se déroule de la même manière, à l’exception du contenu du dump.sh, dont voici le contenu :

#!/bin/bash

#OAR -n Hello_World
#OAR -l /nodes=1/gpu=1,walltime=00:01:30
#OAR -p gpumodel='A100'
#OAR --stdout hello_world.out
#OAR --stderr hello_world.err
#OAR --project test

cd /bettik/bouttier/
/bin/hostname >> dumb.txt

Dans cet exemple, nous demandons un job sur GPU A100.

#OAR -p gpumodel='A100'

Contrairement à la soumission interactive, dans un script de soumission, -p gpumodel='A100' ne s’écrit pas en guillemets.

Mode devel: le bac-à-sable

Le mode de soumission particulier -t devel est disponible pour faciliter la mise au point des jobs. Il est limité à des jobs de 2 heures maximum, et alloue des ressources sur des noeuds dédié à ce mode. Cela permet d’avoir des ressources de type bac-à-sable beaucoup plus disponibles que les ressources de production.

Mais attention, ce bac-à-sable fonctionne sur des GPU plus petites, qui sont en fait des partitions de GPU Nvidia A100. Chaque GPU Nvidia A100 du mode devel est en fait une sous-gpu, que l’on appellera mig par abus de language (MIG=Multi Instance GPU). Aussi la sélection des ressources diffère un peu, et il faudra préciser le nombre de migdevice que l’on veut. En général on n’en demandera qu’un seul car cela n’a pas vraiment de sens de travailler sur plusieurs:

oarsub -l /nodes=1/gpu=1/migdevice=1,walltime=00:10:00 -t devel ...

Noeuds virtuels “Virgo”: T4 GPU pour calculs opportunistes

Le cluster bigfoot héberge également des noeuds “virtuels” auxquels sont associés des petites GPU Nvidia T4. Ces GPU sont utilisées la journée par des étudiants au cours de leurs formations. Elles sont mises à disposition par le projet Fall.

La nuit, à partir de minuit, les machines virtuelles sont allumées en allouant un GPU physique. Les noeuds virgo deviennent actifs dans le cluster Bigfoot, offrant ainsi des ressources Nvidia T4 aux jobs en attente de ce gpumodel. Les machines virtuelles sont éteintes à 6h du matin. Les jobs doivent donc être suffisamment courts (walltime inférieur à 6h) afin d’être autorisés sur ces ressources.

oarsub -l /nodes=1/gpu=1,walltime=04:00:00 -p "gpumodel='T4'" ...

Utiliser les noeuds GPU de Froggy

L’environnement logiciel

Dû à l’ancienneté de la machine, l’environnement logiciel des librairires classiques pour l’utilisation des noeuds est mis en place avec la commande module.

Lancer un job sur les noeuds GPU

Pour lancer un job, nous utilisons toujours le gestionnaire de ressources OAR (dont les commandes essentielles sont décrites dans cette page.), et plus particulièrement la commande oarsub.

En pratique, pour lancer un job sur les noeuds GPU, il faut préciser lors de l’appel à la commande oarsub que le type de notre job sera gpu (-t gpu) et il est possible de préciser le nombre de GPUs que nous voulons pour notre job à l’aide de la propriété gpu (e.g. -l/nodes=1/gpu=2)

Il y a une différence entre Dahu et froggy sur la propriété pour réserver un nombre de GPUs : sur dahu, il faut utiliser la propriété gpudeviceet sur froggy, gpu.

Voici un exemple d’une session interactive où l’on réserve deux GPU, où l’on charge l’environnement CUDA et où l’on compile un utilitaire CUDA :

[bouttier@froggy1 ~] oarsub -I --project test -l /nodes=1/gpu=2 -t gpu
[ADMISSION RULE] Set default walltime to 1800.
[ADMISSION RULE] Modify resource description with type constraints
[COMPUTE TYPE] Setting compute=NO
[GPUNODE] Adding gpu node restriction
OAR_JOB_ID=349170
Interactive mode : waiting...
Starting...
Connect to OAR job 349170 via the node frogkepler3
[bouttier@frogkepler3 ~]$ source /applis/site/env.bash
[bouttier@frogkepler3 ~]$ module load cuda/6.5
[bouttier@frogkepler3 ~]$ rsync -a $cuda_SAMPLES_DIR .
[bouttier@frogkepler3 ~]$ cd cuda-samples/NVIDIA_CUDA-6.5_Samples/1_Utilities/deviceQuery
[bouttier@frogkepler3 deviceQuery]$ make
g++ -m64  -I/opt/cuda/5.0//include -I. -I.. -I../../common/inc -o deviceQuery.o -c deviceQuery.cpp
g++ -m64 -o deviceQuery deviceQuery.o -L/opt/cuda/5.0//lib64 -lcuda -lcudart
mkdir -p ../../bin/linux/release
cp deviceQuery ../../bin/linux/release
[bouttier@frogkepler3 deviceQuery]$ ./deviceQuery
./deviceQuery Starting...

CUDA Device Query (Runtime API) version (CUDART static linking)

Detected 2 CUDA Capable device(s)

Device 0: "Tesla K20m"
 CUDA Driver Version / Runtime Version          5.0 / 5.0
 CUDA Capability Major/Minor version number:    3.5
 Total amount of global memory:                 4800 MBytes (5032706048 bytes)
 (13) Multiprocessors x (192) CUDA Cores/MP:    2496 CUDA Cores
 GPU Clock rate:                                706 MHz (0.71 GHz)
 Memory Clock rate:                             2600 Mhz
 Memory Bus Width:                              320-bit
 L2 Cache Size:                                 1310720 bytes
 Max Texture Dimension Size (x,y,z)             1D=(65536), 2D=(65536,65536), 3D=(4096,4096,4096)
 Max Layered Texture Size (dim) x layers        1D=(16384) x 2048, 2D=(16384,16384) x 2048
 Total amount of constant memory:               65536 bytes
 Total amount of shared memory per block:       49152 bytes
 Total number of registers available per block: 65536
 Warp size:                                     32
 Maximum number of threads per multiprocessor:  2048
 Maximum number of threads per block:           1024
 Maximum sizes of each dimension of a block:    1024 x 1024 x 64
 Maximum sizes of each dimension of a grid:     2147483647 x 65535 x 65535
 Maximum memory pitch:                          2147483647 bytes
 Texture alignment:                             512 bytes
 Concurrent copy and kernel execution:          Yes with 2 copy engine(s)
 Run time limit on kernels:                     No
 Integrated GPU sharing Host Memory:            No
 Support host page-locked memory mapping:       Yes
 Alignment requirement for Surfaces:            Yes
 Device has ECC support:                        Enabled
 Device supports Unified Addressing (UVA):      Yes
 Device PCI Bus ID / PCI location ID:           2 / 0
 Compute Mode:
    < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >

Device 1: "Tesla K20m"
 CUDA Driver Version / Runtime Version          5.0 / 5.0
 CUDA Capability Major/Minor version number:    3.5
 Total amount of global memory:                 4800 MBytes (5032706048 bytes)
 (13) Multiprocessors x (192) CUDA Cores/MP:    2496 CUDA Cores
 GPU Clock rate:                                706 MHz (0.71 GHz)
 Memory Clock rate:                             2600 Mhz
 Memory Bus Width:                              320-bit
 L2 Cache Size:                                 1310720 bytes
 Max Texture Dimension Size (x,y,z)             1D=(65536), 2D=(65536,65536), 3D=(4096,4096,4096)
 Max Layered Texture Size (dim) x layers        1D=(16384) x 2048, 2D=(16384,16384) x 2048
 Total amount of constant memory:               65536 bytes
 Total amount of shared memory per block:       49152 bytes
 Total number of registers available per block: 65536
 Warp size:                                     32
 Maximum number of threads per multiprocessor:  2048
 Maximum number of threads per block:           1024
 Maximum sizes of each dimension of a block:    1024 x 1024 x 64
 Maximum sizes of each dimension of a grid:     2147483647 x 65535 x 65535
 Maximum memory pitch:                          2147483647 bytes
 Texture alignment:                             512 bytes
 Concurrent copy and kernel execution:          Yes with 2 copy engine(s)
 Run time limit on kernels:                     No
 Integrated GPU sharing Host Memory:            No
 Support host page-locked memory mapping:       Yes
 Alignment requirement for Surfaces:            Yes
 Device has ECC support:                        Enabled
 Device supports Unified Addressing (UVA):      Yes
 Device PCI Bus ID / PCI location ID:           132 / 0
 Compute Mode:
    < Default (multiple host threads can use ::cudaSetDevice() with device simultaneously) >

deviceQuery, CUDA Driver = CUDART, CUDA Driver Version = 5.0, CUDA Runtime Version = 5.0, NumDevs = 2, Device0 = Tesla K20m, Device1 = Tesla K20m