2 Commits e4d72f369c ... b237c5281d

Auteur SHA1 Message Date
  Philippe Marion b237c5281d correction checkpoint-user1.oar il y a 6 ans
  Philippe Marion ae1c68ffde checkpoint ajout ex6: dmtcp sur scratch il y a 6 ans

+ 5 - 1
checkpoint/README-checkpoint.md

@@ -17,4 +17,8 @@ Note: mise en œuvre de  DMTCP (Distributed MultiThreaded Checkpointing) http://
 
 ### autres exemples et tests
 
-- **OpenMP**: checkpoint-dmtcp-openmp4.oar, checkpoint-dmtcp-openmp5.oar avec le programme timing-matmul2000.f90
+- **OpenMP**: 
+    - checkpoint-dmtcp-openmp4.oar (avec le programme timing-matmul2000.f90)
+	- checkpoint-dmtcp-openmp5.oar (avec le programme timing-matmul2000.f90)
+
+- **Scratch**: checkpoint-dmtcp-scratch-ex6.oar (scratch-ex6.tgz) : les calculs sont effectués sur l'espace local (scratch). 

+ 191 - 0
checkpoint/checkpoint-dmtcp-scratch-ex6.oar

@@ -0,0 +1,191 @@
+#!/bin/bash
+
+#-------------------  CHECKPOINT  DMTCP ex6 --------------------------- 
+#  
+#
+# commande: oarsub -S ./checkpoint-dmtcp-scratch-ex6.oar
+
+
+#  L'exemple 6 met en oeuvre la possibilité d'effectuer un checkpoint
+#  en travaillant sur le répertoire scratch ET avec une reprise
+#  automatique (option idemtpotent) sur un nœud potentiellement
+#  différent à chaque redémarrage. 
+#  - la seule difficulté est de récupérer les checkpoints sur le HOME_DIR
+#    à chaque fin de run «avorté» (si le walltime est atteint)
+#  - Pour la demo:
+#       - le timer est de 20 minutes
+#       - le walltime fixé à 10mn
+#       - donc 3 runs avec l'option --checkpoint 120 (checkpoint 10mn-120s=8mn)
+
+
+#-------------- paramètres OAR---------------------------
+
+# walltime de 10min
+#OAR -l core=1,walltime=00:10:00 
+#OAR -n dmtcp-scratch
+
+#les jobs successifs ecrivent dans des fichiers différents
+
+#OAR -O OAR-ckpt-dmtcp-ex6.%jobid%.out
+#OAR -E OAR-ckpt-dmtcp-ex6.%jobid%.err
+
+#OAR -q default
+
+# A EDITER apres consultation de :
+#  https://www-calculco.univ-littoral.fr/outils_visu/drawgantt/
+# Si pour une raison d'architecture ( option de compilation)
+# il faut des hôtes/processeurs du même type, par ex: 
+##OAR -p nodemodel = 'Dell_R630' 
+# ou:
+##OAR -p nodemodel = 'Dell_R820' 
+
+# au choix : default ou besteffort
+#OAR -t besteffort
+
+# pour une relance auto (c'est l'objectif!)
+#OAR -t idempotent
+
+# checkpoint OAR 120 s avant le walltime 
+# Pour un exemple réel ( plusieurs heures, gros contexte, 600s (10mn))
+
+#OAR --checkpoint 120
+
+# chargement du module dmtcp
+source /nfs/opt/env/env.sh   > /dev/null 2>&1
+module load dmtcp  > /dev/null 2>&1
+
+#---------- la tâche à exécuter   ------------------------ 
+# doit être contenu dans l'archive ./RUN_DIR.tgz
+
+PROG=timer20mn
+RUN_DIR=scratch-ex6
+
+#----------- pré-traitement -----------------------------
+
+GROUP=$(id -gn $OAR_USER)
+
+# Création du répertoire temporaire local dans scratch
+
+#SCRATCHDIR=/scratch/$GROUP/$OAR_USER/$OAR_JOB_NAME.$OAR_JOBID
+SCRATCHDIR=/scratch/$GROUP/$OAR_USER/$OAR_JOB_NAME
+[ ! -d $SCRATCHDIR ] && mkdir $SCRATCHDIR
+
+# Recopie de l'archive du  programme (et éventuels checkpoints
+# et données des runs précendents) dans le répertoire
+
+cd $SCRATCHDIR
+
+# au 1er lancement, par exemple:
+# backup de l'archive dans le rép d'origine
+# (celle-ci est modifiée à chaque run car contient les checkpoints)
+
+if [ ! -f $OAR_WORKDIR/$RUN_DIR.tgz.ORG ]; then
+    cp $OAR_WORKDIR/$RUN_DIR.tgz $OAR_WORKDIR/$RUN_DIR.tgz.ORG
+fi
+
+# copie sur le scratch
+cp $OAR_WORKDIR/$RUN_DIR.tgz .
+# deploiement de l'archive
+tar xzf $RUN_DIR.tgz 
+# supression de l'archive
+rm $RUN_DIR.tgz
+cd $RUN_DIR
+# sur quel noeud sommes-nous? 
+/bin/hostname
+echo "Debut du jobs ou restart ?"
+
+# si c'est une reprise
+if [ -f dmtcp_restart_script.sh ]; then
+    LAST_HOST=`cat hostname.txt`
+    # sur quel noeud ?
+    /bin/hostname
+    # si le dernier run était sur un autre noeud, modifier
+    # le script de redémarrage
+    if  [ $(hostname) != $LAST_HOST ]; then
+	echo " -> reprise du job sur autre noeud"
+	NEW_HOST=`/bin/hostname`
+	sed -i s/"$LAST_HOST"/"$NEW_HOST"/g dmtcp_restart_script.sh
+	# optionnel (pour debug)
+	cp hostname.txt hostname_last.txt
+	# backup du nouvel hostname
+	/bin/hostname > hostname.txt
+    else
+	echo "-> reprise sur le meme noeud"
+    fi
+    # relancer depuis le dernier checkpoint
+    ./dmtcp_restart_script.sh &
+    PROGPID=$!
+else
+    echo "  -> Debut du jobs"
+    # sauvegarde du hostname 
+    /bin/hostname > hostname.txt
+    dmtcp_launch  ./timer20mn &
+    PROGPID=$!    
+fi
+
+#---------------------------------------------------------
+# gestion du checkpoint  OAR  
+#---------------------------------------------------------
+
+# fonction de traitement du signal OAR
+sighandler() {
+    echo "reception checkpoint OAR (signal12)"
+    # demande de checkpoint (-c) au coordinateur dmtcp
+    dmtcp_command -c
+    sleep 5
+    # regroupement et ménage pour la relance du job
+    # ---------------------------------------------
+    mv $OAR_STDOUT .
+    mv $OAR_STDERR .
+    # archivage des fichiers :hosts, checkpoints ...
+    cd ..
+    tar czf $RUN_DIR.tgz ./$RUN_DIR
+    # recopie sur  $HOME
+    mv $RUN_DIR.tgz $OAR_WORKDIR
+    # menage
+    cd ..
+    rm -rf $SCRATCHDIR
+    # suicide avant que LEON s'en occupe!
+    [ -n "$PROGPID" ] && kill -9 $PROGPID
+    SCRIPT_CHECKPOINTED="YES"
+    }
+
+# signal Unix attendu par OAR (defaut = SIGUSR1/10, forcé ici
+# à 12 par le paramètre --signal 12 (cf. param OAR au début)
+CHKPNT_SIGNAL=12
+
+# valeur de sortie pour l'option "--idempotent"
+# (restart automatique) )
+EXIT_UNFINISHED=99
+
+# indique au script OAR de capter le signal 12 
+trap sighandler  $CHKPNT_SIGNAL
+
+# wait indispensable pour maintien des communucations
+# (signaux) entre ce script et le PROG
+while kill -0 "$PROGPID" 2>/dev/null; do
+    wait $PROGPID
+done
+
+# important : le code 99 doit être retourné pour que l'option
+# idempotent ( relance auto.) soit effective
+[ -n "$SCRIPT_CHECKPOINTED" ] && exit 99
+
+
+#---------------------------------------------------------
+# fin du programme:  postraitement 
+#---------------------------------------------------------
+# DWTFYW!
+echo "---post treatement---"
+# suppression des ckpt (ménage)
+echo "fin effective du programme, suppression des checkpoints"
+rm -f ckpt_*.dmtcp dmtcp_restart_script*
+# a supprimer?
+mv hostname.txt last_hostname.txt
+cd ..
+cp -rp $RUN_DIR $OAR_WORKDIR
+cd ..
+rm -rf $SCRATCHDIR
+# écrasement de la dernière archive intermédiaire par l'originale
+mv $OAR_WORKDIR/$RUN_DIR.tgz.OAR $OAR_WORKDIR/$RUN_DIR.tgz
+exit $?

+ 32 - 27
checkpoint/checkpoint-user1.oar

@@ -8,7 +8,7 @@
 
 # commande: oarsub -S ./checkpoint-user1.oar
 
-# Cet exemple est arrêté 2 fois ( 3 jobs consécutifs pour finir)
+# Cet exemple est arrêté 1 fois ( 2 jobs consécutifs pour finir)
 
 #
 #  IMPORTANT:
@@ -22,8 +22,8 @@
 #
 #  Le programme associé à ce script est un simple compteur
 #   ( 1 incrémentation / secondes ) en C.
-#   - son excécution dur 10 mn
-#   - ce script OAR, pour l'exemple, ne prévoit que 5mn (trop court!) 
+#   - son exécution (normal) dure 4 mn
+#   - ce script OAR, pour l'exemple, ne prévoit que 3mn30 (trop court!) 
 #   - le script OAR reçoit (d'OAR) le signal checkpoint 12.
 #     Il renvoit le signal 2 (SIGINT) au programme timer
 #   - À réception de ce dernier (interruption) le timer sauve
@@ -31,8 +31,8 @@
 #   - timer10mn est arrêté mais est relancé par OAR
 # 
 #-------------- paramètres OAR---------------------------
-#OAR -l cpu=1/core=1,walltime=00:5:00 
-#OAR -n start_and_restart
+#OAR -l cpu=1/core=1,walltime=00:3:30 
+#OAR -n checkpoint-user1
 
 # Les fichiers de sortie sans paramètres $OAR_JOBID
 # (=> les jobs successifs écrivent dans les mêmes fichiers)
@@ -41,11 +41,6 @@
 
 #OAR -q default
 
-#IMPORTANT:
-#   - par NFS: a priori pas de problème
-#   - sur SCRATCH : il faut reprendre sur la même machine
-#  par exemple : 
-#OAR -p network_address = 'orval08' 
 ## besteffort est optionnel 
 #OAR -t besteffort
 ## idempotent ne l'est pas 
@@ -60,14 +55,14 @@
 
 #---------- la tâche à exécuter   ------------------------ 
 # compilation ( peut être commenté si déjà compilé) 
-gcc compteur10mn.c  -o timer10mn
-# Note (compteur10mn.c): gère son propre checkpoint (SIGINT)
+gcc compteur4mn.c  -o timer4mn
+# Note (compteur4mn.c): gère son propre checkpoint (SIGINT)
 #----------- pré-traitement -----------------------------
 # DWTFYW !
 echo "Debut du job ${OAR_JOB_ID}"
 
 #----------- lancement de la tâche ----------------------
-./timer10mn &
+./timer4mn &
 
 #---------------------------------------------------------
 # gestion de signaux
@@ -78,7 +73,22 @@ echo "Debut du job ${OAR_JOB_ID}"
 
 # pid du programme = pid de la dernière commande (: ./timer10mn)
 
-PID=$!
+PROGPID=$!
+
+echo "le PROG PID est : $PROGPID"
+
+# fonction de traitement du signal OAR
+sighandler() {
+    echo "reception checkpoint OAR (signal12)"
+    # demande de checkpoint (-c) au programme
+    # SIGINT = 2 = "CRTL + C" (cf compteur10mn.c)
+    kill -s 2 $PROGPID
+    # IMPORTANT : pause
+    sleep 4
+    [ -n "$PROGPID" ] && kill -9 $PROGPID
+    SCRIPT_CHECKPOINTED="YES"
+    echo "checkpoint : $SCRIPT_CHECKPOINTED"
+    }
 
 # signal Unix attendu par OAR (defaut = SIGUSR1/10, forcé ici
 # à 12 par le paramètre --signal 12 (cf. param OAR au début)
@@ -90,21 +100,16 @@ EXIT_UNFINISHED=99
 
 # si le script OAR reçoit le SIGUSR2 (signal 12), checkpoint!
 
-# Rq tentative d'envoyer le même signal au prog: ne fonctione pas!?
-# SIGUSR2 = 12 kill rééllement le programme :
-#   => pas de checkpoint
-#   => boucle infinie!
-
-# Du coup: 
-# SIGINT = 2 = "CRTL + C" fonctionne 
-trap "echo commande trap (script OAR); kill -s 2 $PID ; exit $EXIT_UNFINISHED" $CHKPNT_SIGNAL
-#
+# indique au script OAR de capter le signal 12 
+trap sighandler  $CHKPNT_SIGNAL
 
-# obliger le script OAR à attendre l'exécution du PROG
-# (sinon il s'exécute jusqu'au bout et ne récupérera
-# jamais le signal checkpoint !)
+# wait indispensable pour maintien des communucations
+# (signaux) entre ce script et le PROG
+while kill -0 "$PROGPID" 2>/dev/null; do
+    wait $PROGPID
+done
 
-wait $PID
+[ -n "$SCRIPT_CHECKPOINTED" ] && exit 99
 
 #---------------------------------------------------------
 # fin du programme:  postraitement

+ 118 - 0
checkpoint/checkpoint-user1bis.oar

@@ -0,0 +1,118 @@
+#!/bin/bash
+
+#-------------------  CHECKPOINT  --------------------------- 
+
+#
+#  exemple de programme qui vient illustrer le cas décrit : 
+# https://www-calculco.univ-littoral.fr/utilisation/lancer-un-calcul#h2-2-oardel
+
+# commande: oarsub -S ./checkpoint-user1bis.oar
+
+# cet exemple reprend l'exemple exemple 1 (checkpoint-user1.oar)
+# avec un programmer timer de 4mn 
+# simplement c'est l'utilisateur qui déclencle le checkpoint
+# en supprimant son job avec la commande:
+
+#    oardel -c -s SIGUSR2 XXXXX, où XXXX est le n° du job (JobID)
+# 
+
+#   Le checkpoint crée le fichier context_compteur.txt. Relancer le
+#   script OAR ultérieurement entraîne un reprise du programme à
+#   partir de ce contexte.
+
+# 
+#-------------- paramètres OAR---------------------------
+#OAR -l cpu=1/core=1,walltime=00:5:00 
+#OAR -n checkpoint-user1bis
+
+# Les fichiers de sortie sans paramètres $OAR_JOBID
+# (=> les jobs successifs écrivent dans les mêmes fichiers)
+#OAR -O OAR-ckpt-user1bis.out
+#OAR -E OAR-ckpt-user1bis.err
+
+#OAR -q default
+
+
+#IMPORTANT:
+#   - par NFS: a priori pas de problème
+#   - sur SCRATCH : il faut reprendre sur la même machine
+#  par exemple : 
+##OAR -p network_address = 'orval08' 
+## besteffort est optionnel 
+#OAR -t besteffort
+
+# signal envoyé par OAR (SIGUSR2)
+#OAR --signal 12 
+
+#---------- la tâche à exécuter   ------------------------ 
+# compilation ( peut être commenté si déjà compilé) 
+gcc compteur4mn.c  -o timer4mn
+# Note (compteur4mn.c): gère son propre checkpoint (SIGINT)
+#----------- pré-traitement -----------------------------
+# DWTFYW !
+echo "Debut du job ${OAR_JOB_ID}"
+
+#----------- lancement de la tâche ----------------------
+./timer4mn &
+
+#---------------------------------------------------------
+# gestion de signaux
+#---------------------------------------------------------
+# Warning: c'est le script OAR qui reçoit le signal 12!
+#  => il faut le capter et le transmettre au PROG
+####################################################
+
+# pid du programme = pid de la dernière commande (: ./timer10mn)
+
+PROGPID=$!
+
+echo "le PROG PID est : $PROGPID"
+
+# fonction de traitement du signal OAR
+sighandler() {
+    echo "reception checkpoint OAR (signal12)"
+    # demande de checkpoint (-c) au programme
+    # SIGINT = 2 = "CRTL + C" (cf compteur10mn.c)
+    kill -s 2 $PROGPID
+    # IMPORTANT: pause (creation du fichier contexte)
+    sleep 5
+    [ -n "$PROGPID" ] && kill -9 $PROGPID
+    SCRIPT_CHECKPOINTED="YES"
+    echo "checkpoint : $SCRIPT_CHECKPOINTED"
+    }
+
+# signal Unix attendu par OAR (defaut = SIGUSR1/10, forcé ici
+# à 12 par le paramètre --signal 12 (cf. param OAR au début)
+CHKPNT_SIGNAL=12
+
+# valeur de sortie en cas de checlpoint :
+# on laisse la valeur 99 nécessaire à l'option "--idempotent"
+# (restart automatique)
+# Dans le cas manuel, cette valeur peut être autre, l'important
+# est d'en fixer une pour sortir du programme sans aller à la fin
+# du script OAR (sinon le contexte est suppimé . cf les dernières lignes) 
+EXIT_UNFINISHED=99
+
+# si le script OAR reçoit le SIGUSR2 (signal 12), checkpoint!
+
+# indique au script OAR de capter le signal 12 
+trap sighandler  $CHKPNT_SIGNAL
+
+# wait indispensable pour maintien des communucations
+# (signaux) entre ce script et le PROG
+while kill -0 "$PROGPID" 2>/dev/null; do
+    wait $PROGPID
+done
+
+# sortir ici ( sinon suppression du fichier context_compteur.txt )
+[ -n "$SCRIPT_CHECKPOINTED" ] && exit $EXIT_UNFINISHED
+
+#---------------------------------------------------------
+# fin du programme:  postraitement
+#---------------------------------------------------------
+# DWTFYW!
+echo " ---post treatement---"
+echo " ...suppression du fichier temporaire context_compteur.txt"
+rm -f context_compteur.txt
+echo " c'est FINI ! "
+exit $?

+ 95 - 0
checkpoint/compteur4mn.c

@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>  //sleep
+
+
+/*
+ - compteur sur 10 mn (affichage incrementations toutes les secondes)
+ - capture de signaux ( pour test de checkpointing avec dmtcp /OAR Caclculco)
+ - le compteur est sauvegardé dans un fichier sur capture de signal (SIGINT /2)
+     -> à réutiliser pour reprise de travaux après checkpointing ) 
+ */
+#define SIZE 1
+#define NUMELEM 5
+
+/*compteur  variable globale ( main et signal ) */
+int compteur;
+//findice_ckpt
+FILE * fp;
+
+
+void sig_handler(int signal)
+{
+switch (signal)
+  {
+  case SIGINT:
+    // code exécuté si on reçoit SIGINt (CTRL+C);        
+    printf("SIGINT recu (programme C)\n");
+    printf("valeur du compteur enregistre: %d\n", compteur);
+    // fichier de sauvegarde du "contexte" ( l'indice = nb de secondes!
+    fp = fopen("context_compteur.txt", "wb");
+    if(fp == NULL) {
+        printf("error creating file");
+    }
+    else {
+      fwrite( &compteur , sizeof(int) , 1 , fp);
+      fflush(fp);
+      fclose(fp);
+    }
+    break;
+
+  case SIGUSR1:        
+    // code normalement exécuté si on reçoit SIGUSR2 (OAR?) ou SIGUSR1 (dmtcp);
+    // NE FONCTIONNE PAS ( c'est donc le SIGINT 2 ci- dessus qui est utlisé dans
+    // checkpoint-user1.oar
+    printf("signal checkpoint SIGUSR1 recu \n");
+    printf("valeur du compteur: %d\n", compteur);
+    fp = fopen("context_compteur.txt", "wb");
+    if(fp == NULL) {
+        printf("error creating file");
+    }
+    else {
+      fwrite( &compteur , sizeof(int) , 1 , fp);
+      fclose(fp);
+    }
+
+    break;
+
+    default :
+    // sortie
+    exit(0);
+  }
+}
+
+
+//int main( int argc, char *argv[] )
+int main(void)
+{
+  if (signal(SIGINT, sig_handler) == SIG_ERR)
+    printf("\n ne peut pas recevoir SIGINT\n");
+
+  // ----- test si un checkpoint existe ---- 
+  // si oui, lecture de la valeur dans le fichier
+  int i ;
+  fp = fopen("context_compteur.txt", "rb");
+  if (fp){
+    fread( &i , sizeof(int) , 1 , fp);
+    printf("valeur compteur au precedent checkpoint = %d\n", i);
+    fclose(fp);
+  }else{
+    i=0;
+  }
+  // ---- le Compteur propremen dit ---------
+  // 10 mn(environ: ce n'est pas un chrono!)
+  
+  for (compteur=i; compteur <=240; compteur++)
+    {
+      printf("compteur = %d\n", compteur);
+      // force l'écriture sur la sortie
+      fflush(stdout);
+      sleep(1);
+    }
+  return 0;
+}

BIN
checkpoint/scratch-ex6.tgz