Gestion avancée des jobs

OAR offre aux demandeurs des possibilités pour gérer plus finement leurs soumissions de jobs. Avant d’aller plus loin ici, il faut avoir bien compris le fonctionenemnt et l’utilisation d’OAR sur nos clusters comme décrit ici.

Le checkpointing

Cette fonctionnalité est encore expérimentale. Nous vous conseillons de la tester avant d’automatiser vos chaînes de calculs et de traitements.

Dans certains cas, les jobs doivent durer plus longtemps que la durée maximale autorisée et le programme n’a pas de moyen de sauvegarder son statut pour pouvoir redémarrer là où il s’est arrêté. Sur les nœuds Dahu, CRIU, couplé à OAR via un démon, permet aux jobs de se contrôler eux-mêmes. CRIU peut sauvegarder un arbre de processus complet (uniquement pour les jobs séquentiels, aucune communication entre les nœuds) et sa mémoire sur le disque pour arrêter le travail et redémarrer à partir de la celui-ci dans un nouveau job.

Un mécanisme simple a été mis en place pour relier CRIU au point de contrôle et aux fonctions idempotentes d’OAR, de sorte qu’un long job est automatiquement contrôlé quelque temps avant le walltime et automatiquement redémarré à la suite.

Pour mettre en place un tel job, vous pouvez adapter le script suivant à vos besoins :

#!/bin/bash
#OAR -n test_script
#OAR -t idempotent
#OAR -l /nodes=1/core=4,walltime=00:5:00
#OAR -O test.%jobid%.stdout
#OAR -E test.%jobid%.stderr
#OAR --project test
#OAR --checkpoint 240
#OAR --notify mail:Bruno.Bzeznik@univ-grenoble-alpes.fr

# Timeout to adapt: 600 is a good value for bigger jobs
RESUME_TIMEOUT=90

# Handler for checkpointing signal sent by OAR
handler() { echo "Caught checkpoint signal at: `date`"
            echo "Checkpointing..."
            echo -e "$PROG_PID\n$(pwd)" > /var/lib/checkpoints/$OAR_JOB_ID.checkpoint
          }
trap handler SIGUSR2

# Load environment
source /applis/site/nix.sh

# A checkpoint exists, resuming it
if [ -e checkpoint_ok ]
then
  rm -f checkpoint/pidfile
  sleep 30
  echo -e "$(pwd)" > /var/lib/checkpoints/$OAR_JOB_ID.resume
  # Wait for the restore (for pidfile to be created)
  declare -i c=1
  while [ \! -e checkpoint/pidfile -a $c -le $RESUME_TIMEOUT ]
  do
    sleep 1
    let c++
  done
  if [ $c -eq $RESUME_TIMEOUT ]
  then
     echo "ERROR: Timeout on resume!" >&2
     exit 3
  fi
  sleep 5
  PROG_PID=$(cat checkpoint/pidfile)

# No checkpoint, starting the program
else
  nohup stress --cpu 4 --io 4 --vm 2 -v  &
  PROG_PID=$!
fi

# Wait for $PROG_PID (`wait` does not work in all cases, and 
# bash kills the script when a trap occurs within a wait)
while [ -e /proc/$PROG_PID ]
do
  sleep 1
done

# Now that the process has exited, we have to wait for the checkpoint
# to be finished. The checkpoint_ok file is removed only before doing
# a new checkpoint.
while [ \! -e checkpoint_ok ]
do
  sleep 1
done

# Idempotent job exits with 99 code to be automatically re-submitted
exit 99

Le répertoire de travail du poste DOIT être sur un système de fichiers partagé, tel que /bettik, car le dump est créé à l’intérieur d’un sous-répertoire de contrôle qui doit être disponible à partir de chaque nœud pour le redémarrage. Tous les fichiers ouverts par votre programme doivent également se trouver sur un système de fichiers partagé, bien sûr (attention aux répertoires temporaires !)

Ce script est à adapter à vos besoins (instructions OAR, exécutable lancé, etc.). Le lancement de votre programme doit être plaacé entre nohup et &. Le & final est crucial, puisque que votre programme doit tourner en arrière plan afin que le script puisse récupérer ensuite son PID pour être checkpointé.

Dans certains cas, le redémarrage peut échouer. Une des raisons est que le PID utilisé par le programme n’a pas pu être restauré parce qu’il était déjà utilisé par un autre processus sur le noeud. Dans ce cas, le système de resoumission automatique est arrêté et vous devrez soumettre à nouveau votre travail manuellement, dans l’espoir que le nouveau travail commence sur un autre nœud avec le PID demandé disponible.

La sortie de votre programme ira toujours dans la sortie du premier job de l’arbre d’exécution idempotent (dans notre exemple, dans la sortie test.%jobid%.stdout, avec le jobiddu job initial).

Tester le checkpointing

Pour tester si le checkpointing marche sur votre job, vous pouvez le forcer :

oardel --checkpoint $JOB_ID

Un répertoire de checkpoint devrait être créé dans le répertoire de travail et le job devrait s’arrêter (être tué). Comme c’est un checkpoint manuel, vous devrez le redémarrer manuellement, donc resoumettez-le via oarsub. Ensuite, vérifiez que le job s’est correctement terminé. Enfin, il est conseillé de recommencer une fois cette opération au moins une fois pour être sûr qu’un job correctement terminé peut égalerment être checkpointé (pour éviter les effets de bords en fin de job).