Placement est un outil développé par CALMIP qui répond à deux objectifs principaux :
- Optimiser l'affinité des processus et des threads en les positionnant de manière appropriée sur les cœurs de calcul, afin d'améliorer les performances, de réduire les coûts de communication et de favoriser la localité mémoire (NUMA).
- Surveiller l'exécution des jobs en fournissant des informations détaillées sur l'utilisation des ressources (cœurs CPU, mémoire, GPU, etc.) et sur le placement effectif des processus et des threads.
Optimiser l'affinité des processus et des threads
Le contrôle du placement des processus MPI et des threads OpenMP est particulièrement important pour les applications hybrides (MPI + OpenMP). Un placement inadapté peut entraîner des migrations de threads, des accès mémoire distants entre nœuds NUMA et, par conséquent, une dégradation significative des performances.
Même pour les applications purement MPI ou purement OpenMP, il est recommandé de vérifier l'affinité des processus et des threads afin de garantir une bonne localité mémoire et une utilisation optimale des ressources du nœud.
L'outil Placement doit être utilisé avec srun. L'utilisation avec mpirun n'est pas prise en charge.
Exemple d'utilisation
L’utilisation de Placement est simple : il suffit de l’intégrer directement dans la commande srun dans le script slurm. L’outil se charge ensuite automatiquement de gérer le placement des processus et des threads.
srun $(placement) mon_executable ...
Avant d’intégrer Placement dans un script de production, il est possible de vérifier son comportement afin de comprendre comment les processus et threads seront répartis sur les ressources allouées. Cela permet d’éviter les mauvaises configurations (affinité incorrecte, déséquilibre NUMA, sur-souscription de cœurs, etc.) avant le lancement réel du calcul.
Supposons un exécutable MPI exécuté sur la partition Kairos avec les caractéristiques suivantes :
- 6 processus MPI par nœud ;
- 4 threads OpenMP par processus ;
Vérifier ce qui va se passer (en théorie) :
# placement 6 4 --ascii
S0---------------------------------------------------------------------------------------------- S1----------------------------------------------------------------------------------------------
P AAAABBBBCCCC.................................................................................... DDDDEEEEFFFF....................................................................................
- Le premier paramètre (
6) est le nombre de processus - Le second paramètre (4) est le nombre de threads par processus
- Le switch (
--ascii) entraîne un affichage en "art ascii", c’est-à-dire une représentation visuelle du placement sur les deux processeurs, uniquement pour un contrôle rapide.
Lecture de la sortie - S0 et S1 représentent les deux sockets du nœud.
- Les lettres A, B, C, D, E, et F représentent les différents processus MPI.
- Chaque occurrence d'une lettre correspond à un cœur utilisé par un thread du processus associé.
Ainsi :AAAA signifie que le processus A dispose de 4 threads, chacun étant associé à un cœur de calcul sur le socket S0.
# placement 4 8 --numactl
--physcpubind=0-3,4-7,8-11,96-99,100-103,104-107
Ce résultat montre comment Placement configure l’affinité CPU en tenant compte de la topologie NUMA du nœud.
Sur Kairos, les nœuds sont composés de 6 domaines NUMA (3 par socket).
Comme on peut le constater dans la première sortie de placemetn, chaque paire de processus se trouve sur un socket.
numactl montre:
- les trois premiers processus sont placés sur le premier domaine NUMA du premier socket ;
- les trois processus suivants sont placés sur le premier domaine NUMA du second socket ;
- la répartition respecte la structure NUMA afin de maximiser la localité mémoire et réduire les accès distants.
Générer les switches qui vont bien pour srun :
# placement 4 8 --srun
--cpu_bind=mask_cpu:0xf,0xf0,0xf00,0xf000000000000000000000000,0xf0000000000000000000000000,0xf00000000000000000000000000
- Les deux premiers paramètres sont inchangés
- Le switch
--srunprovoque la sortie compatible avec le contrôle du placement pour srun. - la sortie par défaut de
placement.
Insérer la commande placement dans le script sbatch:
# srun $(placement) mon_executable ...
- Les paramètres
6et 4 sont superflus à condition que la réservation slurm ait été faite correctement, avec les balises#SBATCH --tasks_per_nodeet#SBATCH --cpus_per_task - Le switch --srun est superflu car la sortie "srun" est la sortie par défaut de placement
- La syntaxe
bash $()remplace ce qui est à l’intérieur des parenthèses par la sortie de la commande, donc srun voit simplement les switches de contrôle du placement.
Il est extrêmement important d’ajouter #SBATCH --cpus-per-task dans votre script lorsque vous utilisez Placement, même si vous n’avez qu’un seul thread par processus.
Après avoir utilisé Placement, vous pouvez désormais visualiser le résultat du placement des processus ainsi que l’utilisation des ressources grâce à Placement en mode monitoring.
Surveiller l'exécution des jobs
Vous pouvez utiliser Placement depuis votre terminal afin d'obtenir des informations détaillées sur les ressources utilisées par vos jobs en cours d'exécution.
Placement fonctionne pour les deux architectures, x86 et Grace Hopper, et s’adapte en fonction du job sur lequel il est exécuté.
Cas 1 : vous n'avez qu'un seul job en cours
Pour afficher les informations relatives à votre unique job en exécution :
placement --checkme
Cas 2 : vous avez plusieurs jobs en cours
Pour surveiller un job particulier, utilisez son identifiant :
placement --jobid=$jobid
où $jobid correspond à l'identifiant du job à analyser.
Cas 3 : votre job s'exécute sur plusieurs nœuds
Pour obtenir les informations concernant un nœud spécifique :
placement --host=$node_name
où $node_name est le nom du nœud à surveiller.
Pour surveiller touts les nœud de job:
placement --host=$(squeue -j $jobid -h -o %N)
Options complémentaires
Les commandes précédentes peuvent être combinées avec différentes options afin d'afficher des informations supplémentaires.
Par exemple, Affichage de l'utilisation mémoire d'un job :
placement --jobid=$jobid --memory
Surveillance en temps réel. L'option --rt permet d'effectuer un suivi continu:
placement --host=$node_name --rt
Cette option peut également être utilisée avec d'autres commandes Placement selon vos besoins.
Pour obtenir la liste complète des options disponibles voire la documentation.
Vérifier que le placement est correct:
Lorsque le job est en exécution, il est utile de vérifier que le placement est correct :

On voit ici que :
- Le placement des threads de chaque processus correspond à ce que l’on souhaite
- La mémoire des processus est allouée sur les bancs connectés au bon processeur
Vérifier l’utilisation du GPU
Lorsqu’un job est exécuté sur un nœud GPU il est également utile de vérifier que les GPUSs sont effectivement utilisés :

On voit ici que :
- Les quatre GPUs du nœud sont utilisés
Les processus A,B,C,D communiqueront chacun avec un GPU ( chaque GPU sur un socket)
La documentation de placement
La documentation complète de placement peut se lire par :
placement --documentation
L’aide rapide est accessible par :
placement --help
On peut trouver d’autres informations sur le wiki de placement