Turing : travaux multi-étapes

Attention : si vous faites des transferts de fichiers avec Ergon, nous vous conseillons plutôt de consulter la page sur les travaux multi-étapes avec transferts de fichiers avec Ergon.

Un job comprend souvent un phase de préparation des données, de transferts de fichiers entre différents répertoires (pour les transferts avec Ergon, voir cette page), une phase de calcul parallèle, puis une phase de traitement des résultats.

Il serait dommage de monopoliser des milliers de cœurs Blue Gene/Q pendant les phases purement séquentielles. Aussi, nous allons utiliser la notion d'étape (ou step) de LoadLeveler : les trois phases décrites précédemment peuvent être enchaînées dans un même job. Les phases séquentielles seront exécutées sur la machine frontale (Power7) et la phase de calcul parallèle sur les noeuds de calcul de la machine.

Notes importantes :

  • Sur Turing le répertoire TMPDIR est conservé entre les différentes étapes d'un même job ;
  • La frontale n'étant pas une machine destinée à faire des pré- et post-traitements lourds, les ressources allouées aux classes séquentielles sont volontairement limitées. La machine Adapp est par contre dimensionnée pour ce type d'usages ;
  • Les classes séquentielles de Turing ne sont pas facturées.

Voici un exemple de travail enchaînant la préparation des données, l'exécution d'un programme MPI avec 2048 tâches sur 1024 cœurs puis l'archivage des résultats dans une dernière étape :

job_multi.ll
#=========== Global directives ===========
#@ shell    = /bin/bash
#@ job_name = test_multi-steps
#@ output   = $(job_name).$(step_name).$(jobid)
#@ error    = $(output)
 
#=========== Step 1 directives ===========
#======= Sequential preprocessing ========
#@ step_name = sequential_preprocessing
#@ job_type  = serial
#@ wall_clock_limit = 0:15:00
#@ queue
 
#=========== Step 2 directives ===========
#============= Parallel step =============
#@ step_name  = parallel_step
#@ dependency = (sequential_preprocessing == 0)
# (executed only if step 1 completed without error)
#@ job_type   = bluegene
#@ bg_size    = 64
#@ wall_clock_limit = 1:00:00
#@ queue
 
#=========== Step 3 directives ===========
#======= Sequential postprocessing =======
#@ step_name  = sequential_postprocessing
#@ dependency = (parallel_step >= 0) && (sequential_preprocessing == 0)
# (executed even if step 2 completed with an error but only if step 1 is successful)
#@ job_type   = serial
#@ wall_clock_limit = 0:15:00
#@ queue
 
case $LOADL_STEP_NAME in
 
  #============ Step 1 commands ============
  #======= Sequential preprocessing ========
  sequential_preprocessing )
    set -ex
    cd $tmpdir
    cp $LOADL_STEP_INITDIR/test/src/coucou_MPI.f .
    mpixlf90_r coucou_MPI.f -o coucou_MPI.exe
 
    tar xvf $WORKDIR/mydata/data.tar
    ls -l
    ;;
 
  #============ Step 2 commands ============
  #============= Parallel step =============
  parallel_step )
    set -x
    cd $tmpdir
    runjob --ranks-per-node 32 --np 2048 --mapping ABCDET : ./coucou_MPI.exe my_args
    ;;
 
  #============ Step 3 commands ============
  #======= Sequential postprocessing =======
  sequential_postprocessing )
    set -x
    cd $tmpdir
    tar cvf $WORKDIR/results/result.tar *.dat
    ;;
esac

Ce job est séparé en deux sections. La première contient l'ensemble des directives destinées au gestionnaire de queues LoadLeveler, tandis que la deuxième rassemble les commandes à exécuter par les différentes étapes (steps). Les deux parties peuvent également être mélangées mais cela risque de nuire à la lisibilité et à la compréhension du job.

Les directives LoadLeveler de chaque step doivent se terminer par une directive #@ queue.

Dans ce job, notez l'utilisation dans la première étape de la commande set -ex (Bash shell). Elle permet d'interrompre l'étape en cours dès qu'une commande renvoie un code de retour différent de zéro.
Ainsi, en prenant en compte la relation de dépendance #@ dependency = (sequential_preprocessing == 0) dans la deuxième étape, la step 2 ne s'exécutera que si toutes les commandes de la step 1 se sont correctement exécutées. Si la commande set -ex n'est pas utilisée, alors le test de dépendance de l'étape 2 se fait sur le code de retour de la dernière commande de l'étape 1.
Pour la troisième étape, la dépendance choisie est telle que l'étape s'exécutera même en cas d'erreur lors de la seconde étape (cela peut être très utile pour récupérer des résultats partiels même après un crash de l'application ou un dépassement de temps) mais uniquement si la première étape s'est bien terminée (dans le cas contraire, il n'y a pas d'intérêt à exécuter cette troisième étape).

Il est nécessaire de mettre des directives de dépendances si l'on veut s'assurer que les différentes étapes s'exécutent les unes après les autres (sans cette directive, toutes les steps peuvent démarrer indépendamment les unes des autres dès que des ressources sont disponibles).

La soumission de ce travail crée en réalité trois travaux contenant le même script shell (mais recevant des ressources différentes). Ils ne se distinguent que par leur nom d'étape. Pour qu'ils exécutent chacun des commandes différentes, il est nécessaire d'effectuer un branchement différent pour chaque step en utilisant leur nom (stocké dans la variable LOADL_STEP_NAME). Cela est fait via l'utilisation d'un case. Son utilisation est simple, il suffit de vous inspirer de l'exemple. N'oubliez pas d'ajouter ;; (double point-virgule) pour séparer chaque branche et esac à la fin.

Pour soumettre ce travail à trois étapes, placez-vous dans le répertoire contenant job_multi.ll et tapez :

llsubmit job_multi.ll

Notez également que, lors du démarrage de chaque step, le répertoire par défaut est celui d'où a été soumis le job ; c'est là que seront écrits les fichiers de sortie. D'autre part, il est indispensable de spécifier un fichier de sortie différent pour chaque step, faute de quoi la sortie du dernier step écrase les sorties des précédents (voir la ligne output dans le fichier de soumission). Enfin, les différentes options de la commande runjob sont détaillées dans cette page.