Le gestionnaire de batch Slurm permet aux utilisateurs d’associer aux jobs des champs optionnels au format texte, tel que le nom du job ou un commentaire. Ces champs ne sont pas directement utilisés par Slurm, leur valeur n’a pas d’influence sur son comportement. Ils sont librement disponible pour stocker des données qui sont liées aux jobs, en les manipulant à travers les commandes standards de Slurm. Ces champs peuvent par exemple se réveler utiles pour différencier, filtrer, classifier ou annoter des jobs.
Nous allons voir dans ce post une méthode pour utiliser le champ de commentaire pour associer des metadonnées structurées aux jobs et enrichir les rapports d’accounting avec des informations personnalisées.
Le commentaire peut être défini à la soumission des jobs avec l’argument --comment
:
$ sbatch --comment hello --wrap "sleep 60"
Submitted batch job 943
Il est alors visible avec la commande scontrol show job $ID
:
$ scontrol show job 943
JobId=943 JobName=wrap
…
Comment=hello
…
Il est également possible de définir le commentaire pendant l’exécution du job
avec la commande scontrol update job $ID
.
Par défaut, le commentaire est mémorisé par Slurm tant que le job est en file du
scheduler (en attente, bloqué ou en cours d’exécution). Une fois le job terminé,
le commentaire est perdu. Il est cependant possible de configurer Slurm pour
enregistrer le commentaire dans la base de donnée d’accounting SlurmDBD, en
activant ce paramètre dans le fichier de configuration slurm.conf
:
AccountingStoreFlags = job_comment
Les commentaires des jobs deviennent alors persistants après la fin des jobs et
ils peuvent être récupérés avec la commande d’accounting Slurm standard sacct
.
Le champ de commentaire peut stocker un texte, sans contrainte particulière sur son format. Ce texte peut notamment être une représentation sérialisée d’une structure de données, tel que JSON.
Voici un exemple de script de batch shell simpliste comment.sh
qui positionne
un commentaire un tableau associatif une clé mesh et une valeur entière
aléatoire à la fin de son exécution :
#!/bin/sh
# compute stuff here
MESH=$(shuf -i 0-1000 -n 1)
scontrol update job $SLURM_JOB_ID comment="{\"mesh\": ${MESH}}"
En soumettant par exemple deux jobs avec ce script de batch :
$ sbatch comment.sh
Submitted batch job 894
$ sbatch comment.sh
Submitted batch job 895
Il est ensuite possible d’extraire cette métadonnée de l’accounting, en couplant
la sortie de la commande sacct
à l’utilitaire jq
:
$ sacct --json | jq '.jobs | map({id: .job_id, user: .user, cores: .required.CPUs, meta: .comment.job|fromjson })'
[
{
"id": 894,
"user": "remi",
"cores": 1,
"meta": {
"mesh": 760
}
},1
{
"id": 895,
"user": "remi",
"cores": 1,
"meta": {
"mesh": 720
}
}
]
Voici un exemple plus avancé de script Python comment.py
qui met à jour le
commentaire en fin d’exécution avec un tableau associatif de 3 clés et des
valeurs de types différents :
1#!/usr/bin/python3
2import signal
3import time
4import atexit
5import sys
6import os
7import subprocess
8import random
9import json
10
11def save_metadata():
12 """Save computation metadata in Slurm job's comment."""
13 job_id = os.getenv('SLURM_JOB_ID')
14 metadata = {
15 'mesh': random.randrange(0, 1000),
16 'complexity': random.random(),
17 'tag': random.choice(['choose', 'among', 'three']),
18 }
19 cmd = ['scontrol', 'update', 'job', job_id, f"comment={json.dumps(metadata)}"]
20 print(f"Saving metadata in Slurm job {job_id} comment field")
21 subprocess.run(cmd)
22
23
24def handle_timeout(signum, frame):
25 """Signal handler which stops the computation."""
26 signame = signal.Signals(signum).name
27 print(f"Signal {signame} ({signum}) received due to job timeout, saving "
28 "metadata and exiting properly")
29 sys.exit(0)
30
31
32def main():
33 # Bind SIGUSR1 sent by Slurm to notify of approaching job's timelimit
34 signal.signal(signal.SIGUSR1, handle_timeout)
35 # Register save_metadata() function to run just before exiting the program
36 atexit.register(save_metadata)
37
38 # Start fake computation for 5 minutes
39 print("Starting computation")
40 time.sleep(300.) # simulating long interruptible computation
41
42
43if name == '__main__':
44 main()
Le script enregistre la fonction save_metadata()
(l11) avec le module
atexit (l36) pour gérer correctement les cas d’erreur et les interruptions
de l’exécution par Slurm, par exemple en cas d’atteinte de la limite de temps ou
de préemption.
Ce script a une durée d’exécution approximative de 5 minutes. Il est soumis à
Slurm une première fois avec une limite à 10 minutes pour lui laisser le temps
de se terminer normalement, et une deuxième fois avec une limite à 3 minutes en
demandant à Slurm d’envoyer un signal SIGUSR1
60 secondes avant sa
terminaison :
$ sbatch --time 10 --wrap "srun python3 -u comment.py"
Submitted batch job 10773
$ sbatch --time 3 --signal USR1@60 --wrap "srun python3 -u comment.py"
Submitted batch job 10774
Voici les sorties des jobs obtenues dans les deux cas :
$ cat slurm-10773.out
Starting computation
Saving metadata in Slurm job 10773 comment field
$ cat slurm-10774.out
Starting computation
Signal SIGUSR1 (10) received due to job timeout, saving metadata and exiting properly
Saving metadata in Slurm job 10774 comment field
Dans le cas où le job se termine normalement, la fonction save_metadata()
est
exécutée en fin de job. Dans le cas où le job doit se terminer à cause de sa
limite, le script reçoit le signal SIGUSR1
, exécute le handler
handle_timeout()
qui provoque l’arrêt du script, ce qui déclenche l’exécution
de la fonction save_metadata()
.
Nous pouvons ensuite bien extraire ces métadonnées fictives de la base d’accouting Slurm :
$ sacct --json | jq '.jobs | map({id: .job_id, user: .user, cores: .required.CPUs, meta: .comment.job|fromjson })'
[
{
"id": 10773,
"user": "remi",
"cores": 1,
"meta": {
"mesh": 376,
"complexity": 0.2924316126744422,
"tag": "among"
}
},
{
"id": 10774,
"user": "remi",
"cores": 1,
"meta": {
"mesh": 157,
"complexity": 0.7724739043178511,
"tag": "three"
}
}
]
Cette fonctionnalité peut se révéler intéressante pour associer diverses metadonnées aux jobs Slurm, notamment pour générer des indicateurs et des métriques supplémentaires et personnalisées dans les rapports d’accounting des calculateurs.