Actuellement, nous avons deux clusters de calculs, dénommés respectivement Hades et Lucifier pour les technologies Intel et AMD, dont en voici les principales caractéristiques techniques:
Chaque compte utilisateur est rattaché à un groupe qui possède chacun trois types de quotas: quota d'espace disque, quota de fichiers et quota de temps de calculs. Si vous souhaitez davantage d'information concernant votre quota, veuillez contacter votre responsable de projet (votre encadrant).
Pour permettre à tout un chacun de travailler de manière collégiale sans alterer les performances globales, je vous saurais gré de respecter, dans vos scripts, les règles d'écritures suivantes:
Pour l'utilisation des espaces de travail temporaires dans le /scratch de chaque noeud de calculs ou dans l'espace partagé /scratch-dfs, veuillez respecter l'arborescence suivantes /scratch[-dfs]/<your group>/<JOBID> sans quoi vos données seraient détruites lors du nettoyage automatique.
Pour les jobs mono-nodes, n'oubliez pas de récupérer vos données à la fin de vos jobs, sans quoi vos données seraient là-également détruites.
De plus, l'ensemble des noeuds de calculs étant “stateless” (le système d'exploitation n'est pas installé sur les noeuds), ne stoquez pas de données sur les noeuds (exemple: dans le /tmp) car elles seraient irrémédiablement perdues lors du prochain redémarrage.
Les clusters Hades (Intel) comme Lucifer (AMD) sont tous deux gérés par le gestionnaire de travaux Torque (fork d'OpenPBS) conjointement au scheduler Maui et un gestionnaire d'allocations (i.e. quota) Gold.
Vous trouverez des scripts d'introduction vous permettant de mettre en oeuvre facilement, et dans le respect des règles/politiques d'utilisation, vos travaux dans le répertoire /shared/scripts/ accessibles des deux masters. Ces scripts portent le suffix “ADMIN_”.
NOTE: N'UTILISEZ PAS LES COMMANDES (BASH BUILTINGS & BINARIES) DE TYPE NOHUP, DISOWN, ETC. QUI MAINTIENDRAIENT EN VIE VOS JOBS SUR LES CLUSTERS.
Cela aurait pour effet de vous permettre d'utilisez les ressources en toute discression (aucun décompte de temps, etc.) mais casserait le fonctionnement du cluster (performance, etc.).
Si d'aventure cela était remarqué sur les clusters -la tricherie n'étant pas admise- vos comptes seraient désactivés et seuls vos supérieurs hiérarchiques (ou le directeur du laboratoire) seraient habilités à m'en demander leur réouverture.
Lancer un job décrit dans le script <jobscript>
qsub <jobscript>
Lancer une session interactive sur le cluster
qsub -I -A <your allocation|project account>
Consulter la liste des jobs soumis:
qstat
Supprimer un job:
qdel <jobid>
Obtenir des informations sur un job soumis:
checkjob <jobid>
Visualiser graphiquement les ressources (disponibles et/ou utilisées, etc.)
pbstop
Obtenir des informations sur un job en cours
checkjob -vv <jobid>
Obtenir les statistiques (au sens résumé) d'utilisation du cluster pour un projet donné
gusage -s 20140101 -h -p simlab_project
Obtenir la liste des jobs qui ont été exécuté sur une période donnée (par exemple, du 01/01/2014 à maintenant)
gstatement -s 20140101 -h -p simlab_project
NB : l'option –summarize permet de résumer cette liste.
Connaitre l'état de ses allocations de temps de calculs
mybalance -h
Afficher les ressources disponibles (autrement qu'avec pbstop)
showbf
Connaitre/estimer le démarrage d'un job mis en queue
showstart <jobid>
Lister les jobs actuellement en queue
showq
NB : bien sur, l'ensemble de ces commandes permettent un ensemble de dérivées au gré des paramètres saisis; n'hésitez donc pas à utiliser les man ou l'aide (–help) pour en savoir davantage.
#!/bin/sh ############################# # les directives PBS vont ici: # your job shell environment #PBS -S /bin/bash # Your job name (displayed by the queue) #PBS -N helloWorld # Your job outputs (standard output & error) #PBS -o helloWorld.out #PBS -e helloWorkd.err # Specify the working directory #PBS -d . # walltime (hh:mm::ss) #PBS -l walltime=00:10:00 # needed ressources (here 1 node and 32cores per node) #PBS -l nodes=1:ppn=32 # Allocation source #PBS -A admin_project # To be aware about execution progress # abe: to be aware about aborting, beginning and/or ending execution #PBS -m abe #PBS -M geoffrey.letessier@ibpc.fr # fin des directives PBS ############################# # modules environment module load torque # useful informations to print echo "#############################" echo "User:" $USER echo "Date:" `date` echo "Host:" `hostname` echo "Directory:" `pwd` echo "PBS_JOBID:" $PBS_JOBID echo "PBS_O_WORKDIR:" $PBS_O_WORKDIR echo "PBS_NODEFILE: " `cat $PBS_NODEFILE | uniq | sort` echo "#############################" ############################# # What you actually want to run echo "Hello World" sleep 30 # fake # all done echo "Job finished"
En supposant que le script ci-dessus soit enregistré dans un fichier dénommé test.sh, vous pouvez le soumettre au gestionnaire de travaux :
qsub test.sh
NB : afin d'être correctement lues et prises en compte par Torque, les directives PBS (#PBS) doivent impérativement se situées au début du script, avant toute directive de type shell. Dans le cas contraire elles seront ignorées (les détails sont fournis dans la documentation Torque de qsub).
NB : si vous n'aviez pas spécifié les directives de redirection des flux de sortie et d'erreur standard, ces derniers auraient été créés dans le répertoire courant sous la nomenclature suivante :
stdout: <jobname>.o<jobid>
stderr: <jobname>.e<jobid>
Afin de permettre un fonctionnement normal du gestionnaire de travaux, vous êtes obligés de spécifier les ressources dont vous avez besoin pour votre calcul. Dans le cas où vous omettez de les spécifier, une valeur par défaut est prise telle que décrite ci-dessous.
Les paramètres “ressources” importantes:
Exemples :
L'ajout d'options à la commande qsub n'est utile que si ces options ne sont pas déjà spécifiées dans le script du job (<script>) lui même.
job séquentiel de 2 heures
qsub -l walltime=2:00:00 <script>
job openmp 4 coeurs (sur un seul noeud) de 1 jour
qsub -l walltime=24:00:00 -l nodes=1:ppn=4 <script>
job parallèle de 200 coeurs (répartis au hasard) # pas très compatible avec le fonctionnement voulu du cluster
qsub -l select=200:ncpus=1 <script>
job parallèle de 120 coeurs avec 10 noeuds complets:
qsub -l nodes=10:ppn=12 <script>
Lister les queues et informations inhérentes
qstat -q
Connaître les ressources disponibles
showbf
Cette commande fournit le nombre de coeurs disponibles pour plusieurs durées. showbf -h donne une liste des options disponibles.
Evaluer la date de départ d'un job
showstart <JOBID>
Donne des informations utiles sur la date de départ (prévisible) d'un job, ainsi qu'une estimation de sa date de terminaison.
Avoir des informations sur les jobs (actifs, en attente ou bloqués)
showq
showq -h pour plus de détails
On peut avoir besoin d'accéder à une ressource de calcul pour y exécuter des commandes interactivement (cycle développement↔compilation) ou lancer des applications qui nécessitent l'intervention de l'utilisateur (debugger, etc…).
Pour avoir une connexion sur un noeud de calcul, il suffit d'ajouter l'option -I à la commande qsub. On se passe alors de script et un shell est ouvert sur la ressource dès qu'elle est allouée. Les entrées-sorties de ce shell sont connectées sur le terminal qui exécute qsub.
Exemple :
qsub -I
La configuration particulière du cluster impose de prendre certaines précautions selon la version de MPI qu'on veut utiliser.
Pour un simple test, OpenMPI sera le plus simple à mettre en œuvre:
#!/bin/sh #PBS -l nodes=2:ppn=12 #PBS -N OPENMPI module load torque module load openmpi myapp=<chemin-vers-application> # pour éviter certains warnings: export IPATH_NO_CPUAFFINITY=1 mpirun $myapp
Le cluster Hades (technologie Intel) est principalement composé de deux types de serveurs de calcul (voir Environnement matériel):
Aux vues de la quantité de RAM présent sur les noeuds Dell, ceux-ci portent l'étiquette bigmem.
Aux vues du nombre de coeurs présent sur le noeud 30, celui-ci porte l'étiquette monop
Exécuter un job sur la partition “bigmem” (uniquement disponible sur Hades)
Pour lancer un job Torque sur la partition bigmem, vous devez simplement préciser la partition “:bigmem” dans les spécifications des ressources requises:
#PBS -l nodes=1:ppn=12:bigmem
Le cluster Lucifer (technologie majoritairement AMD) est quant-à-lui intégralement composé comme suit :
Aux vues des caractéristiques techniques des noeuds 59 et 60, ceux-ci porteront l'étiquette monop.
Aux vues des caractéristiques techniques des noeuds 61 et 62, ceux-ci porteront l'étiquette gpu.
Les performances CPU entre les deux technologies CPU majoritaires (AMD Opteron 6282SE et AMD Opteron 6380) étant comparables, il n'est pas nécessaire de partitionner “physiquement” le cluster en 2.
La partition par défaut concerne tous les noeuds à l'exception :
Torque permet l'exécution de scripts dits prologue et épilogue en encapsulation d'un job.
Bien que généralement réservés/destinés aux administrateurs du système, l'utilisateur peut spécifier des scripts personnels au moment de la soumission des jobs (voir la documentation Torque) :
qsub -l prologue=<path_to_prologue_script> epilogue=<path_to_epilogue_script> <jobscript>
On notera que ces jobs doivent être relativement courts (~ moins de 5 minutes) et qu'ils ne sont exécutés que sur le premier des noeuds alloués au job. On peut récupérer les informations du job dans les scripts par les arguments de la ligne de commande.
L'intérêt de cette fonctionnalité est de permettre l'exécution d'un script hors du job proprement dit. Ca signifie entre autres que l'épilogue sera exécuté même quand le job est en erreur, a été supprimé ou a dépassé son walltime associé.
On peut notamment utiliser ce mécanisme pour récupérer les résultats locaux d'un job en cas d'erreur, faire du nettoyage spécifique en fin de job, etc…
NB : n'oubliez pas d'ajouter les permissions d'exécution sur le script d'épilogue car, à défaut, ce dernier étant exécuté sous un shell amoindri, il ne sera pas exécuté et vos données perdues…
exemple : chmod u+x epilogue.sh
Synchroniser un répertoire local avec un répertoire réseau lors d'un job.
La solution d'épilogue peut être insuffisante ou inadaptée à vos besoins; en effet, il vous est peut-être nécessaire de suivre les traitements au fil de l'eau et attendre la fin d'exécution d'un job pour la synchronisation des répertoires ne vous le permet pas. Une solution existe: créer un script pour synchroniser régulièrement des répertoires locaux avec une espace partagé que vous planifierez avec la commande “at” (exemple: pour synchronisation toutes les 5 minutes: “at now +5 minute <sync_script>”) ou encore créer un script “infini” qui fera une synchronisation toutes les N secondes jusqu'à la fin du temps d'exécution du job.
Voici un exemple de script ($HOME/automatic_rsync.sh) qui permettra d'y pallier:
#!/bin/bash # script to regularly reync the current working directory with source one: pbs_o_workdir # default delay value is set to be equal to 10 minutes (here: 600 secondes) if [ -n "$1" ] && [[ $1 =~ ^[0-9]+$ ]]; then DELAY=$1 else DELAY=600 fi while true ; do sleep $DELAY rsync -ap $WORKDIR/ $PBS_O_WORKDIR/ done
que vous pourrez appeler au début de votre script de job via un appel en background: ~/automatic_rsync.sh & (ou “~/automatic_rsync.sh 3600 &” pour une synchronisation toutes les heures)
NB : n'oubliez pas d'ajouter les permissions d'exécution sur le script de synchronisation automatique.
exemple: chmod u+x automatic_rsync.sh
Il est possible avec la commande qsub, de lancer un grand nombre de jobs en une seule fois, en utilisant l'argument -t. On peut spécifier le nombre de jobs via une liste d'indexes, exemple :
qsub -t 1-3
qsub -t 1,3,4,5-10
ou, dans un script PBS, par :
#PBS -t 1-3,10-20
Un identifiant de la forme xxxx[yyyy] est attribué à chaque job, avec yyyy pris parmi les indexes spécifiés par -t, et tout les jobs seront sous un même identifiant global xxxx[].
Par exmple, si on utilise -t 1,5,7, les JOBIDs résultants seront :
1234[1].torque2
1234[5].torque2
1234[7].torque2
pour voir l'état des jobs groupés, on utlise la commande qstat, comme suit :
$ qstat -t 1234[]
Job id Name User Time Use S Queue ------------------------- ---------------- --------------- -------- - ----- 1234[1].torque2 myjob_in_out-1 fake 0 Q small 1234[5].torque2 myjob_in_out-5 fake 0 Q small 1234[7].torque2 myjob_in_out-7 fake 0 Q small
ou individuellement (job par job) par la commande qstat 1234[1].
$ qstat 1234[1]
Job id Name User Time Use S Queue ------------------------- ---------------- --------------- -------- - ----- 1234[1].torque2 myjob_in_out-1 fake 0 Q small
Lancer un job avec le même exécutable et plusieurs fichiers d'entrée/sortie.
Les variables $PBS_ARRAYID et $PBS_JOBID peuvent être utilisées dans les scripts.
Si vous avez par exemple plusieurs fichiers de données/entrée et vous voulez les traiter par un même exécutable, vous pouvez utiliser dans ce cas un tableau de job.
Voici un exemple :
Supposons que vous avez 3 fichiers de données :
data1.in
data5.in
data7.in
et pour chaque fichier de données data<k>.in correspond un fichier de sortie de type data<k>.out, le script suivant permet de créer un tableau de job :
!/bin/sh ## fichiers d'entrée et sortie de soumission #PBS -o testArray.out #PBS -e testArray.err #PBS -l nodes=1:ppn=3 #PBS -t 1,5,7 # Informations sur le job echo "Job Id:" $PBS_JOBID echo "List of nodes allocated for job (PBS_NODEFILE): " `cat $PBS_NODEFILE | uniq | sort` ### Load modules needed ### module load torque cd $PBS_O_WORKDIR myapp=./hello_in_out $myapp data${PBS_ARRAYID}.in data${PBS_ARRAYID}.out
Il est également possible de chainer ses jobs, à comprendre conditionner l'exécution d'un job en fonction du résultat (bonne exécution) d'un autre job.
Pour ce faire, il suffit d'ajouter le paramètre “-W depend=afterok:<JOBID>” à la soumission du second job.
$ qsub job1.sh
1235.torque1.cluster.lbt
$ qsub -W depend=afterok:1235.torque1.cluster.lbt job2.sh
1236.torque1.cluster.lbt
Vous pourrez naturellement compiler vos propres applications/librairies, que ce soit sur l'espace commun (si vous faites partie du groupe UNIX install_team) ou sur votre espace personnel.
Pour ce faire, vous devez ouvrir une session interactive (avec les ressources escomptées) et utiliser les compilateurs à votre disposition pour compiler (compilateur Intel dans l'espace commun ou GNU sur les noeuds eux-mêmes).
NB : les masters ayant des librairies propres et n'ayant pas le même OS que les noeuds de calculs, vous ne devez pas compiler quoi que ce soit sur les masters.
Quand on utilise un UNIX de manière générale, il n'est pas rare de devoir surcharger les variables d'environnement SHELL pour pouvoir utiliser ses applications et/ou librairies. Ceci est d'autant plus vrai si ces applications et/ou librairies sont installées dans des arborescences propres (i.e. qui ne sont pas celles par défaut).
Un problème survient rapidement: la multiplication des applications/librairies utilisées rend rapidement illisible le fichier de configuration du shell et complexifie énormément leur utilisation au quotidien (conflits, versionnement, etc.)
Pour faciliter leur gestion, nous avons installé sur les clusters un gestionnaire de variables d'environnement qui traite chaque application/librairie comme un module optionnel à charger/décharger au besoin.
Lister les modules existants
On peut lister l'ensemble des modules existants grâce à la commande “module (av|avail)”:
$ module avail
------------------------------------------------------------------ /shared/modulefiles/compilers ------------------------------------------------------------------- intel/12.0.5 mpiexec/gnu/0.84 openmpi/gnu/1.5.4_centos openmpi/intel/1.6.5 python/gnu/2.7.5 intel/14.0 openmpi/gnu/1.4.4 openmpi/gnu/1.6.5 openmpi/intel_12.0.5/1.6.5 ------------------------------------------------------------------ /shared/modulefiles/libraries ------------------------------------------------------------------- atlas/gnu/3.10.1 blas/gnu cblas/gnu fftw/gnu/3.3.3 lapack/gnu/3.4.2 openblas/gnu ------------------------------------------------------------------ /shared/modulefiles/softwares ------------------------------------------------------------------- amber/gnu/12 gromacs/gnu/4.6.1 gromacs/gnu/4.6.3_intelnodes namd2/gnu/2.9_gpu namd2/multicore_gpu amber/gnu/14 gromacs/gnu/4.6.3 namd2/gnu/2.8 namd2/intel/2.9 R/gnu/2.14.2 amber/gnu/14_gpu gromacs/gnu/4.6.3_gpu namd2/gnu/2.9 namd2/multicore R/gnu/3.0.1 ------------------------------------------------------------------ /shared/modulefiles/utilities ------------------------------------------------------------------- bonnie++/gnu/1.03e ddt/gnu/8 emacs/gnu/24.3 HPL-Linpack/gnu/2.1 iozone/gnu/3 torque/gnu/2.5.12 cmake/gnu/2.8.11.2 ddt/gnu/9 fpart/gnu/0.9 hwloc/gnu/1.7.1 parallel/gnu/20140822
ou encore seulement lister les modules existants pour une application particulière par la commande “module (avail|av) <module name>”:
$ module avail gromacs
------------------------------------------------------------------ /shared/modulefiles/softwares ------------------------------------------------------------------- gromacs/gnu/4.6.1 gromacs/gnu/4.6.3 gromacs/gnu/4.6.3_gpu gromacs/gnu/4.6.3_intelnodes
Charger un module
Pour charger un module, il faut simplement utiliser la sous-commande “load”.
$ module load torque
Loads the torque-2.5.12 compiled using gnu-4.4.6
Noter que dans les modules que je vous prépare, vous obtenez quelques informations telles que la version ou encore son compilateur, voire ses dépendances si nécessaire…
Vous pouvez vérifier que les binaires sont bien accessibles via la commande which:
$ which qsub
/shared/utilities/torque/2.5.12/gnu/bin/qsub
Décharger un module
Vous pouvez décharger un module en utilisant la sous-commande “unload”.
$ module unload torque
On peut vérifier que le binaire n'est plus accessible:
$ which qsub
/usr/bin/which: no qsub in (/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin)
Lister les modules chargés
Vous pouvez à tout moment lister l'ensemble des modules qui composent votre environnement en la sous-commande “list”.
$ module list
Currently Loaded Modulefiles: 1) openmpi/gnu/1.6.5 2) torque/gnu/2.5.12
Remplacement de module
Imaginez le cas où vous auriez chargé un module dans une version spécifique mais que vous souhaiteriez le remplacer par une autre version. Vous pourriez simplement décharger l'ancien et charger le nouveau par les commandes précitées. Environment-Module permet de le faire plus rapidement grâce à la sous-commande “switch”.
$ module list
Currently Loaded Modulefiles: 1) torque/gnu/2.5.12 2) openmpi/gnu/1.6.5
$ module switch openmpi/gnu/1.4.4
$ module list
Currently Loaded Modulefiles: 1) torque/gnu/2.5.12 2) openmpi/gnu/1.4.4
NB : Attention toutefois au nommage du module: ici, seule la version peut être chargée, pas le compilateur…
Comment créer ses propres modules
Vous pouvez naturellement créer vos propres modules, dans votre répertoire personnel, en créant un répertoire dédié, en surchargeant la variable d'environment $MODULEPATH.
$ mkdir ~/modules # uniquement si le répertoire n'existe pas :)
$ export MODULEPATH=$HOME/modules:${MODULEPATH}
$ cp /shared/cluster_help/module.template ~/modules/<module_name>
Il ne vous reste plus qu'à éditer le module en question pour en modifier les variables.
J'invite tout lecteur à consulter les documentations officielles (Torque, Environment-Module, etc), ou les manuels (man <commande>) pour une utilisation plus approfondie des concepts sus-cités. En effet, cette “doc” n'a de fin que d'initier les utilisateurs novices à l'utilisation des ressources computationnelles du LBT.