À quoi ça sert
gbind est un script à interposer entre le lanceur MPI et votre exécutable. Il est lancé une fois par rang MPI et, pour chaque rang, il :
- attribue un GPU (sélectionné par UUID) ;
- exporte la carte réseau InfiniBand la plus proche de ce GPU ;
- épingle le processus sur le nœud NUMA Grace correspondant (CPU + mémoire, via
numactl) ; - applique un jeu de variables UCX orientées GPUDirect RDMA ;
- gère, si demandé, l'ensemble du cycle de vie MPS (démarrage du démon, répartition des SM, arrêt et nettoyage).
Quand plusieurs rangs se partagent un GPU, la répartition est calculée automatiquement à partir du nombre de tâches et du nombre de GPU alloués : rangs_par_gpu = ceil(tâches / GPU), en distribution par blocs.
Utilisation
Important : toujours passer -bind-to none (avec mpirun). C'est gbind qui doit maîtriser le placement ; sinon le lanceur et le script se contredisent.
srun gbind ./mon_applimpirun -n 4 --bind-to none gbind ./mon_appli
Aide sur n'import quelle architecture ( sur login nœud ou même sur nœud calcule) : gbind --help
Exemple : script SLURM
script 4 processus avec 2 gpu ( 2 processus par gpu) no MPS.
4 rangs pour 2 GPU, donc 2 rangs par GPU. Les rangs 0 et 1 utilisent le premier GPU (mlx5_0, nœud NUMA 0), les rangs 2 et 3 le second (mlx5_1, nœud NUMA 1).
#!/bin/bash
#SBATCH --job-name=mon_calcul
#SBATCH --nodes=1
#SBATCH --ntasks=4
#SBATCH --ntasks-per-node=4
#SBATCH --gres=gpu:2
#SBATCH --partition=shared-gpu
#SBATCH --cpus-per-task=36
#SBATCH --time=00:30:00
module purge
module load nvidia
module load nvhpc-hpcx
srun gbind ./mon_appli
mpirun -n 4 --bind-to none gbind ./mon_appli
Attention: Partage d'un GPU sans MPS. Les contextes CUDA se partagent le GPU en temps partagé : les noyaux ne s'exécutent pas simultanémen
Options (variables d'environnement)
| Variable | Default | Description |
|---|---|---|
| MPS | 0 | Active MPS de bout en bout : un seul démon par nœud, 100/rangs_par_gpu % des SM par rang, arrêt et nettoyage automatiques. |
| RDMA_PERF | 1 | Applique le réglage UCX GPUDirect RDMA (UCX_TLS, UCX_RNDV_SCHEME, UCX_RNDV_THRESH, UCX_IB_GPU_DIRECT_RDMA). Mettre 0 pour laisser UCX à ses valeurs par défaut. |
| NGPU | — | N'utiliser que les N premiers GPU alloués (ex. NGPU=3 si le nœud entier vous a été réservé mais que vous ne voulez travailler que sur 3 GPU). |
| GPUS | — | Utiliser exactement ces GPU, par indice nvidia-smi (ex. GPUS=0,2). |
| BIND_CPUNODE | 1 | Épinglage CPU sur le nœud Grace (numactl --cpunodebind). Mettre à 0 sous srun pour conserver le cpuset par tâche fourni par SLURM. |
| BIND_MEM | 1 | Épinglage mémoire (numactl --membind). |
| BIND_NIC | 1 | Affectation de la carte InfiniBand la plus proche. |
| BIND_NUMA | 1 | Interrupteur général du placement numactl. |
| SET_CUDA_VISIBLE | 1 | Exporte CUDA_VISIBLE_DEVICES (par UUID). |
| VERBOSE | 1 | 0 : silencieux ; 1 : une ligne par rang ; 2 : ajoute la vérification nvidia-smi et les avertissements. |
Chaque option s'active de deux façons, au choix — en préfixe de la commande de lancement, ou par export :
OPTION1=valeur OPTION2=valeur srun gbind ./mon_appli
OPTION1=valeur OPTION2=valeur mpirun -n 4 --bind-to none gbind ./mon_appli
#OU
export OPTION=valeur
srun gbind ./mon_appli
Vérifier que le placement est correct
Avec VERBOSE=1, chaque rang affiche une ligne du type :
[nœud grank=2 lrank=2] GPU logical=1 slot=1 bus=00000019:01:00.0 uuid=GPU-a476...
CUDA=GPU-a47650ee... share=2/gpu UCX=mlx5_1:1 cpunode=1 memnode=1 MPS=0
À contrôler : les rangs qui doivent partager un GPU affichent le même UUID, les autres un UUID différent ; la carte mlx5_* et les nœuds NUMA correspondent bien au GPU.
Avec VERBOSE=2, s'ajoutent la sortie nvidia-smi du GPU retenu, la liste des cœurs autorisés, et des avertissements en cas d'incohérence.