Gestion des jobs

Introduction au gestionnaire de jobs

Notion de cluster

Un cluster est un ensemble de machines qui se compose d’une frontale, ou plusieurs frontales, et de noeuds de calcul. Une frontale est la machine sur laquelle l’utilisateur se connecte en ssh, tandis que les noeuds sont les machines sur lesquelles l’utilisateur fait tourner ses programmes.

Tous les programmes que l’utilisateur lance se font depuis une frontale en utilisant un gestionnaire de ressources chargé de trouver et d’allouer les ressources requises parmi les noeuds.

Le gestionnaire de ressources utilisé est OAR.

Notion de job

Un job est ce que l’utilisateur soumet au gestionnaire de ressources pour éxécuter un programme. Il est composé d’une description des ressources nécessaires à l’exécution du programme et les commandes permettant cette exécution, généralement fournies dans un script.

Parmi les ressources requises par le gestionnaire de ressources pour la soumission d’un job, on a le nombre de noeuds, de coeurs par noeud, et le temps de calcul maximal. Si l’utilisateur omet ces informations, le gestionnaire applique des valeurs par défaut. Les défauts sont 1 noeud, 1 coeur et 2h maximum.

Un job a un cycle de vie, il est :

  1. Soumis au gestionnaire
  2. En attente de ressources libres (Waiting)
  3. En exécution (Running)
  4. Terminé (Terminated)

Commandes OAR de gestion des jobs

Soumettre un job

La commande pour soumettre un job est oarsub. Cette commande a de nombreuses options que l’on peut trouver en utilisant l’option help : oarsub --help.

Soumission de base

La forme la plus basique d’utilisation est celle où on précise uniquement le projet et la commande à lancer : oarsub --project <your-project> <command>

Par exemple, ci-dessous un exemple de soumission de la commande /bin/hostname :

[cgirpi@froggy1 ~]$ oarsub --project cecipex /bin/hostname
[ADMISSION RULE] Set default walltime to 1800.
[ADMISSION RULE] Modify resource description with type constraints
[COMPUTE TYPE] Setting compute=YES
[ADMISSION RULE] Antifragmentation activated
[ADMISSION RULE] You requested 0 cores
[ADMISSION RULE] No antifrag for small jobs
OAR_JOB_ID=15576103

Chaque job est identifié de façon unique par son identifiant de job (OAR_JOB_ID). Dans l’exemple, cet identifiant a pour valeur 15576103.

Attention, la commande que vous passez en argument de oarsub, et que vous voulez exécuter sur le noeud, doit avoir les droits d’exécution. et être accessible depuis les noeuds. En particuier si le chemin d’accès n’est pas dans la variable d’environnement PATH, il faut alors passer en argument la commande avec son chemin complet.

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 30 minutes 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.

A compter de février 2024, les noeuds du bac-à-sable sont accessibles depuis une frontale spécifique servant également à faire les tests de pré-production de la nouvelle version de OAR (v3). L’utilisation reste la même, mais il faut simplement se connecter à la frontale dahu-oar3 avant de pouvoir lancer un job de developpement:

# Connect to the dahu-oar3 frontend
ssh dahu-oar3
# Launch a devel job with the '-t devel' option and a walltime less than 30 minutes
oarsub -l /nodes=1/core=1,walltime=00:10:00 -t devel ...

Pour faciliter le passage d’une frontale à l’autre sans avoir à taper de mot de passe, nous vous conseillons d’installer une clé ssh locale si cela n’est pas déja fait, depuis la frontale de Dahu:

user@f-dahu:~$ ssh-keygen -t rsa
user@f-dahu:~$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

Soumission avec demande explicite de ressources

Avec la soumission de commande précédente, nous n’avons demandé aucune ressource spécifique. Ainsi, en message de retour, le gestionnaire de ressources OAR nous a alloué le walltime par défaut (1800 secondes) et nous indique qu’aucun coeur de calcul n’a été demandé.

Walltime et fin de job Si votre job se termine normalement (ou plante !) avant le temps indiqué par le walltime, tout va bien, les ressources sont libérées aussitôt. En revanche, s’il est encore en cours d’exécution à la fin du walltime, il sera tué. Assurez-vous donc de spécifier un walltime suffisant pour qu’il puisse se terminer dans le temps imparti, mais pas trop grand afin qu’il ne patiente pas inutilement dans la file d’attente du gestionnaire de ressources.

Pour réserver des ressources explicitement, il faut utiliser l’option -l de la commande oarsub. Par exemple :

bouttier@froggy1 $ oarsub --project test -l /nodes=4/core=1,walltime=1:00:00 /bin/hostname
[ADMISSION RULE] Modify resource description with type constraints
[COMPUTE TYPE] Setting compute=YES
[ADMISSION RULE] Antifragmentation activated
[ADMISSION RULE] You requested 4 cores
[ADMISSION RULE] No antifrag for small jobs
OAR_JOB_ID=15676746

Avec cette commande, nous avons demandé 1 coeur sur 4 noeuds, soit un total de 4 coeurs, pour une durée maximale (walltime) d’une heure.

Comme nous l’avons vu auparavant, chaque job est identifié à l’aide d’un numéro unique pour chaque cluster contenu dans la variable d’environnement $OAR_JOB_ID, ici 15676746. Par défaut, comme le job s’exécute sur des ressources non accessibles directeemnt, nous n’avons pas accès aux sorties standard et erreur dans lesquelles nos commandes peuvent renvoyer des informations. En réalité, ces sorties sont recopiés dans deux fichiers propres à chaque job, nommés respectivement OAR.$OAR_JOB_ID.stdoutet OAR.$OAR_JOB_ID.stderr. Ces fichiers sont créés par OARla où vous avez soumis votre job.

Les mots-clés les plus couramment utilisés sont décrits dans ce tableau :

Mots-clésSignification
nodesNb de noeuds demandés
coreNb de coeurs demandés
cpuNb de cpu demandés
walltimeTemps maximal d’exécution demandé

Voici plusieurs exemples de réservations de ressources :

oarsub -l /nodes=10,walltime=00:05:00 --project test /bin/hostname

Ici, nous réservons 10 noeuds complets pour 5 minutes dee temps d’exécution maximal.

oarsub -l /core=54,walltime=00:00:30 --project test /bin/hostname

Dans ce cas, 54 coeurs sont réservés, que le gestionnaire va choisir en fonction des disponibilités de la machine (sur un nombre indéfini de noeuds au moment de la soumission), le tout pour 30 secondes de temps d’exécution.

oarsub -l /nodes=3/cpu=1, walltime=2:00:00 --project test /bin/hostname

Enfin, ici, nous demandons 3 noeuds avec 1 cpu sur chacun (les autres cpu de ces noeuds soeront donc dédiés à d’autres jobs), pour 2 heures de temps d’exécution maximal.

La mémoire vive La mémoire vive qui vous est allouée est celle correspondant aux coeurs que vous avez réservés. Ainsi, si vous réservez 1 noeud entier, vous avez accès à la totalité de la mémoire vive (RAM) du noeud. En revanche, si vous demandez n coeurs, vous aurez accès à `RAM_du_noeud*(n/nb_total_de_coeurs_sur_le_noeud)


Paramètres oarsub -l, -t et -p

La demande de ressources spécifiques se fait au moyen des paramètres -l, -t et -p de oarsub. Le paramètre -l sert à quantifier les ressources demandées, -t pour cibler un type spécifique et -p pour contraindre certaines propriétés des ressources.

Il vous appartient de demander des ressources cohérentes avec les ressources disponibles sur les clusters. Vous pouvez obtenir des informations sur ces ressources via les commandes recap.py, chandler et oarnodes en plus des informations présentes dans cette documentation.

Paramètre -l

Avec le paramètre -l vous contrôlerez la topologie, au sens de la hiérarchie des ressources du cluster, et le walltime de votre demande.

Pour un cluster HPC (Dahu, Luke), au plus simple, cette topologie est :

graph LR; B[switch] B -->|/| C[node] C -->|/| D[cpu] D -->|/| E[core]

Pour un cluster GPU comme Bigfoot elle devient :

graph LR; B[switch] B -->|/| C[node] C -->|/| D[gpu] D -->|/| E[migdevice]

Préciser switch=1 permet d’assurer que tous les éléments suivants de la demande sont reliés à un seul et même switch. Attention, si vous ne définissez pas plus précisément votre requète, elle revient à demander tous les cœurs de calcul rattachés à un même switch !

switch=2/node=1 demanderait un noeud sur deux switchs distincts pour un total de deux noeuds complets. Une demande plus cohérente serait switch=1/node=2 qui assurerait que les deux nœuds demandés sont raccordés au même switch ce qui pourrait avoir une importance pour des calculs répartis.

node=1/cpu=1/core=16 demanderait 16 coeurs d’exécution sur un même processeur d’un seul noeud.

node=1/gpu=1 demanderait une GPU complète sur un noeud.

Un exemple de paramètre -l complet pourrait donc être : -l "/node=1/cpu=1/Core=16,walltime=02:00:00".

Un contre exemple assez fréquent est -l "/node=1/cpu=3" qui ne peut pas fonctionner puisqu’aucun nœud ne possède trois CPU sur Dahu. À la soumission vous aurrez une erreur : There are not enough resources for your request.

Toute propriété peut servir de valeur pour le paramètre l. Il faut juste la considérer du point de vue de la quantification des ressources et qu’elle ait du sens dans la topologie du cluster. Par exemple, spécifier cpumodel=1 revient à s’assurer que tous les cœurs de calcul sont pris sur un même modèle de processeur (sans imposer de modèle spécifique contrairement à -p) quel que soit le nœud où ils sont pris.

Paramètre -t

Le paramètre -t permet de sélectionner le type de job soumis, ce qui va sélectionner certains types de ressources avec potentiellement des règles d’admission spécifiques. Si il n’est pas spécifié, le type par défaut est automatiquement attribué.

Sur Dahu les possibilités sont :

  • devel - job de développement, cf. ci-dessus.
  • heterogeneous - permet aux jobs de s’éxécuter sur tous les nœuds du cluster sans se limiter à la partition initiale homogène.
  • fast - job ciblant exclusivement les ressources CPU haute fréquence, plus rapides mais avec moins de cœurs par CPU.
  • fat - job ciblant exclusivement les ressources à très haute cappacité mémoire.
  • besteffort - utile via CiGri.
  • visu - Visualisation.

Sur Bigfoot elle sont :

  • devel - job de développement, cf. ci-dessus.
  • heterogeneous - permet aux jobs de s’éxécuter sur tous les nœuds du cluster sans se limiter à la partition initiale homogène.
  • besteffort - utile via CiGri.

Sur Luke elles sont :

Type hétérogène et Dahu.
le type hétérogène est particulièrement important sur Dahu. Si ce type n’est pas spécifié, les jobs ne tourneront que sur la partition initiale, homogène, du cluster.
La partition homogène est constituée des nœuds avec des charactéristiques identiques aux premiers nœuds ajoutés au cluster. Sur un cluster comme Dahu qui a été construit par des ajouts successifs au cours du temps, cette partition est relativement petite.
Si vous voulez que votre job ne soit pas limité à cette seule partition pour son exécution, il est impératif de préciser le paramètre -t heterogeneous.

Paramètre -p

Toutes les autres propriétés sont sélectionnables via le paramètre -p, qui peut être spécifié de multiples fois.

Quelques propriétés utiles sont, par exemple, pour Dahu :

  • cpumarch
  • cpumodel
  • cpufreq
  • memcore
  • n_cores
  • total_mem
  • scratchX
  • scratchX_type
  • scratchX_loc

et pour Bigfoot :

  • gpumodel
  • mem_per_gpu
  • scratchX
  • scratchX_type
  • scratchX_loc

Les autres propriétés ne sont soit pas utiles pour la sélection de ressources, soit exploitées via d’autres mécanismes (-l et -t). Les utiliser se révèlera contre productif sans une maîtrise très poussée de leur fonctionnement combiné à un cas d’usage très spécifique.

Plus de lecture

Vous pouvez consulter la documentation de OAR sur la commande oarsub : http://oar.imag.fr/docs/latest/user/commands/oarsub.html
Notez cependant qu’elle peut différer un peu de l’implémentation sur les clusters Gricad.


Soumettre un job interactif

Une pratique courante pour bien appréhender la calcul sur un cluster est de soumettre un job interactif. En bref, voous demandez des ressources, et le gestionnaire de ressources va vous connecter sur l’une d’entre elle (un noeud sur lequel elle vous a alloué un coeur) à partir duquel vous pourrez lancer vos commandes/scripts/programmes en interactif. A la fin du walltime, votre session est automatiquement tuée. Si vous la quittez avant, le gestionnaire libérera vos ressources.

La soumission en interactif se fait à l’aide de l’option -I de la commande oarsub. Par exemple :

bouttier@froggy1 $ oarsub -I -l /nodes=1,walltime=1:00:00 --project admin
[ADMISSION RULE] Modify resource description with type constraints
[COMPUTE TYPE] Setting compute=YES
[ADMISSION RULE] Antifragmentation activated
[ADMISSION RULE] You requested 16 cores
[ADMISSION RULE] Disabling antifrag optimization as you are already using /node property
OAR_JOB_ID=15676747
Interactive mode : waiting...
Starting...

Connect to OAR job 15676747 via the node frog80

bouttier@frog80 $

Nous pouvons faire ici plusieurs remarques :

  • Nous avons lancé oarsubsur la frontale (froggy1 dans la premier prompt)
  • L’option -I a été bien rajoutée
  • Nous n’avons pas indiqué de commande à exécuter (absence de /bin/hostname)
  • Le gestionnaire de jobs nous a alloué 16 coeurs puisque nous avons demandé 1 noeud entier (qui comportent 16 coeurs sur le cluster froggy)
  • Une fois le job interactif lancé, nous sommes connecté à notre job via le noeud frog80

Nous voyons qu’ici, avec le deuxième prompt, nous sommes connecté sur le noeud frog80à partir duquel nous pourrons manipuler les fichiers, lancer des commandes, des scripts en interactif. Pour quitter le job, il suffit de quitter le noeud via la commande exit.

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

La soumission interactive est utile pour prendre en main le cluster, faire des tests. En revanche, pour lancer automatiquement un ensemble de commande (préparation de fichier, préparation de l’environnement logiciel, exécution du programme principal, récupération des fichiers de sorties et nettoyage), il est très peu recommandé.

Dans ce cas d’utilisation, nous allons soumettre un job via un script de soumission. Ce script de soumission peut-être écrit dans différents langages interprétés, le plus souvent bashet python.

Le script de soumission va contenir l’ensemble des instructions dont vous avez besoins pour effectuer votre expérience ainsi que des directives OAR qui indiqueront aux gestionnnaires de ressources tout ce dont vous avez besoin. Ces directives sont signalées par la chaîne de caractères #OARen début d’une ligne. Attention, #OARn’est pas un commentaire de votre script de soumission.

Le script de soumission sera ensuite passé en paramètre à la commande oarsub à l’aide de l’option -S. Il faudra préalablement l’avoir rendu exécutable à l’aide de la commande chmod +x.

Comme mille mots valent bien une image, passons à un exemple concret. Voici un script de soumission complètement inutile mais qui illustrera tous les mécanismes que nous avons besoin de présenter ici. Nous l’appellerons donc logiquement dumb.sh dont voici le contenu :

#!/bin/bash

#OAR -n Hello_World
#OAR -l /nodes=2/core=1,walltime=00:01:30
#OAR --stdout hello_world.out
#OAR --stderr hello_world.err
#OAR --project test

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

On peut distinguer deux grandes parties dans ce script :

  • Une partie dédiée aux directives qui seront lues par OAR, indiquées par #OAR
  • Les directives exécutées sur les ressources réservées sur le cluster.

Pour ces dernières, ce script, qui ne va fonctionner que sur les clusters lukeet dahu, va :

  • se déplacer dans le dossier /bettik/bouttier/
  • Écrire la sortie de la commande /bin/hostname dans le fichier dumb.txt. Pour qu’il fonctionne sur froggy, il faudrait travailler dans le dossier /scratchen lieu et place du dossier /bettik.

Pour les directives OAR,nous remarquons ici quelques options connues de oarsub. Regardons ligne par ligne ce que nous demandons au gestionnaire de ressources :

#OAR -n Hello_World

Ici, nous nommons notre job hello_world.

#OAR -l /core=1,walltime=00:01:30

Nous demandons 1 coeur pour 1 minutes 30 secondes maximum.

#OAR --stdout hello_world.out

Le fichier de sortie standard s’appellera hello_world.out.

#OAR --stderr hello_world.err

Le fichier d’erreur standard s’appellera hello_world.err.

#OAR --project test

Nous indiquons que nous appartenons au projet test.

En réalité, ces directives reprennent les options que nous passons en temps normal à la commande oarsub. Il est à noter que toutes les options décrites ici peuvent être utilisées en ligne de commande avec oarsub

Ici, les fichiers de sorties standard et erreur sont nommés indépendamment de l’identifiant de job. Cela peut être dangereux, parce que si soumettez plusieurs fois le script, cahque job écrira dans ce fichier et nous perdrons potentiellement les informations relatives à chaque job.

Avant de soumettre le script, il faut d’abord le rendre exécutable :

chmod +x dumb.sh

Maintenant, nous pouvons soumettre le script :

oarsub -S ./dumb.sh

Une fois les ressources demandées disponibles, la série de commandes décrite dans le script s’exécutera.

Jobs moldable

Un job moldable s’obtient en enchaînant plusieurs directives -l dans une même commande oarsub. Par exemple :

oarsub -l "/nodes=1/core=32,walltime=08:00:00" -l "/nodes=1/core=16,walltime=14:00:00" --project test runme.sh 

Vous donnez, avec cette requète, la possibilité à OAR de choisir l’une ou l’autre de vos demandes de ressources en fonction des disponibilités du cluster. Il choisira automatiquement celle qui se finira en premier.

Suivre un job

Pour connaître l’état et les caractéristiques d’un job soumis, il faut utiliser la commande oarstat. Exécutée toute seule, cette commande renverra l’état des jobs soumis par l’ensemble des utilisateurs sur le cluster. Pour des raisons de lisibilités, nous allons la restreindre à un seul utilisateur à l’aide de l’option -usuivie du login :

bouttier@f-dahu:~$ oarstat -u bouttier
Job id    S User     Duration   System message
--------- - -------- ---------- ------------------------------------------------
4936641   W bouttier    0:00:00 R=1,W=0:1:30,J=B,N=Hello_World,P=admin,T=heterogeneous

Le résultat donne l’ensemble des jobs soumis par cet utilisateur. Nous voyons qu’il n’en a qu’un. Nous voyons son identifiant, son état (ici, W pour waiting, il est en attente de lancement), combien s’est écoulé depuis le début de son exécution (ici 0 puisqu’il est encore en attente) et ses caractéristiques (ressources demandées, walltime, nom, projet, type).

Pour connaître les informations détaillées d’un job, une fois muni de son identifiant, nous pouvons exécuter la commande suivante :

bouttier@f-dahu:~$ oarstat -f -j 4936641
Job_Id: 4936641
    job_array_id = 4936641
    job_array_index = 1
    name = Hello_World
    project = admin
    owner = bouttier
    state = Terminated
    wanted_resources = -l "{type = 'default'}/core=1,walltime=0:1:30"
    types = heterogeneous
    dependencies =
    assigned_resources = 1067
    assigned_hostnames = dahu66
    queue = default
    command = dumb.sh
    exit_code = 32512 (127,0,0)
    launchingDirectory = /home/bouttier
    stdout_file = hello_world.out
    stderr_file = hello_world.err
    jobType = PASSIVE
    properties = ((((hasgpu='NO') AND compute = 'YES') AND sequential='YES') AND desktop_computing = 'NO') AND drain='NO'
    reservation = None
    walltime = 0:1:30
    submissionTime = 2019-11-01 16:17:58
    startTime = 2019-11-01 16:18:09
    stopTime = 2019-11-01 16:18:11
    cpuset_name = bouttier_4936641
    initial_request = oarsub -S dumb.sh; #OAR -n Hello_Worl; #OAR -l /core=1,walltime=00:01:3; #OAR --stdout hello_world.ou; #OAR --stderr hello_world.er; #OAR --project admi
    message = R=1,W=0:1:30,J=B,N=Hello_World,P=admin,T=heterogeneous (Karma=0.000,quota_ok)
    scheduledStart = no prediction
    resubmit_job_id = 0
    events =
2019-11-01 16:18:12> SWITCH_INTO_TERMINATE_STATE:[bipbip 4936641] Ask to change the job state

Ici, la ligne state = Terminatednous indique qu’il est maintenant terminé.

Supprimer un job

Si vous avez lancé un job et que vous vous êtes apercu qu’il est inutile qu’il se poursuive (calcul inutile, erreur dans le script de soumission, etc.) vous pouvez supprimer votre soumission à l’aide de la commande oardel :

bouttier@f-dahu:~$ oarsub -S dumb.sh
[PARALLEL] Small jobs (< 32 cores) restricted to tagged nodes
[ADMISSION RULE] Modify resource description with type constraints
OAR_JOB_ID=4936645
bouttier@f-dahu:~$ oardel 4936645
Deleting the job = 4936645 ...REGISTERED.
The job(s) [ 4936645 ] will be deleted in the near future.

Le karma

Sur un cluster OAR, vous pouvez voir une valeur de karma lorsque vous soumettez un travail interactif, ou lorsque vous demandez le statut d’un job (oarstat -j $JOB_ID) ou lorsque vous vérifiez vos données comptables. Il s’agit d’une valeur utilisée pour assurer le partage équitable des ressources que nous utilisons sur chaque cluster de GRICAD. Le partage équitable signifie que le système essaie de permettre l’utilisation des ressources avec équité entre les utilisateurs. Plus votre karma est faible, plus vous avez de chances que vos travaux commencent avant ceux d’un utilisateur qui a une valeur karma plus élevée. Le karma est fonction du temps de calcul que vous avez demandé et effectivement consommé dans le passé (pendant une fenêtre coulissante, généralement une semaine ou deux selon la plateforme). Mais notez que le karma (et l’algorithme de partage équitable) n’est utilisé que lorsque le système est totalement occupé. La plupart du temps, la programmation est de type FIFO avec rétro-remplissage.