= SoftWare/SignalCheckpoint / OAR - utilisation avec le scheduleur OAR = OAR est un gestionnaire de batch. C'est celui que nous utilisons au LEGI. Il est développé sur Grenoble : http://oar.imag.fr/ Sur cette page ne sont décrit que les spécificité de l'utilisation de la bibliothèque {{{SignalCheckpoint}}} avec le scheduleur OAR. L'objectif est de lancer un code avec l'option de relance automatique en fin de traitement tant que le calcul n'est pas finit ({{{idempotent}}}). On lance un calcul de 24h et 10min avant la fin, {{{OAR}}} envoie le signal {{{SIGUSR2}}} au code pour lui demander de s'arrêter. A noter que les scripts de soumission sont écrit en {{{bash}}} mais devrait fonctionner à l'identique sous {{{ksh}}}. Il faut cependant oublier le {{{csh}}} (et le {{{tcsh}}}) qui ne gère pas les signaux correctement. == Cas simple - sans post-traitement == Le script de soumission configure l'environnement du calcul en chargeant quelques modules puis en exécutant un pré-traitement. Comme il n'y a pas de post-traitement à réaliser, le plus simple est de passer la main au programme de calcul via la directive du shell {{{exec}}}. Ainsi, le script de soumission s'arrête très rapidement et {{{OAR}}} enverra ces signaux directement au code de calcul. A lui de les gérer. On remarque donc sur cet exemple que le script de soumission n'a donc pas à gérer les signaux. L'optimisation via {{{exec}}} permet en plus de récupérer un peu de mémoire vive pour le code ! {{{ #!/bin/bash #OAR -n MYCODE #OAR -t idempotent #OAR --checkpoint 600 #OAR -l /core=1,walltime=24:00:00 # Load environment . /etc/profile module load intel/2011.7 # Pretreatment possible here # Start / give the hand to the code exec ./mycode }}} == Cas asynchrone - avec post-traitement == Il y a de nombreux cas ou le script de soumission doit reprendre la main après l'exécution du code de calcul. Cependant, il faut savoir que le shell ne gère les signaux qu'entre deux instructions, ou lors d'instruction bloquante interne au shell (par exemple {{{wait}}}). L'exemple suivant par exemple ne fonctionne pas car le script exécutera le code dans {{{trap}}} qu'une fois le code {{{mycode}}} finit, donc en pratique jamais car le code dure plus de 24h. Au final, au bout de 24, {{{OAR}}} fera un {{{kill}}} violent du code... {{{ #!/bin/bash #OAR -n MYCODE #OAR -t idempotent #OAR --checkpoint 600 #OAR -l /core=1,walltime=24:00:00 # Signal child retransmit trap 'kill -USR2 $(jobs -p)' USR2 # Load environment . /etc/profile module load intel/2011.7 # Pretreatment possible here # Start / give the hand to the code ./mycode # Post-treatment possible here }}} Une solution est de lancer le code en asynchrone afin que le script de soumission reprenne le plus vite possible la main. Cependant, il doit quand même attendre la fin du code avant de faire l'étape de post-traitement. Voici une solution fonctionnelle à ces impératifs {{{ #!/bin/bash #OAR -n MYCODE #OAR -t idempotent #OAR --checkpoint 600 #OAR -l /core=1,walltime=24:00:00 # Signal child retransmit trap 'kill -USR2 $(jobs -p)' USR2 # Load environment . /etc/profile module load intel/2011.7 # Pretreatment possible here # Launch the code and take back the hand (asynchrone) ./mycode & # Wait for the end of the code while [ $(jobs -p | wc -l) -gt 0 ] do wait done # Post-treatment possible here }}} La boucle '''{{{while}}}''' est très importante car le code peut finir suite à la réception d'un signal mais aussi naturellement lorsqu'il a enfin finit son traitement global. Les deux cas doivent être gérés. Or la commande interne '''{{{wait}}}''' attends la '''fin du calcul''' ou la '''réception d'un signal'''. Une fois le signal reçu, la commande '''{{{trap}}}''' retransmet le signal au code, et le script de soumission repars dans la boucle {{{while}}} afin d'attendre la fin réelle du code. Sans cette boucle, il passerait de suite sur la phase de post-traitement et se terminerait en laissant {{{OAR}}} tuer sauvagement le code dans sa phase terminale... Ce script utilise trois commandes internes du shell peu usitées : {{{wait}}}, {{{trap}}} et {{{jobs}}}. Le premier paramètre de {{{trap}}} est du code shell à exécuter lors de la réception du signal sur lequel on se connecte. Si l'on veut que ce code shell soit effectivement interprété lors de la réception du signal et non avant, il est '''très''' important de la placer entres des '''apostrophes''' (quote)... La commande interne '''{{{jobs}}}''' permet enfin de récupérer l'ensemble des PID des processus fils, donc ici le PID du code de calcul. On le voit, le cas asynchrone oblige à tout gérer dans son script shell. Si cela est possible, il est donc préférable d'éviter les sections en post-traitement.