Table des matières

Présentation des clusters et des règles d'usage

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:

  1. cluster Intel
    1. master: hades.lbt.ibpc.fr
    2. 356 coeurs de calculs
    3. 1248GB de RAM
  2. cluster AMD
    1. master: lucifer.lbt.ibpc.fr
    2. 976 coeurs de calculs
    3. 1152GB de RAM
  3. ressources communes:
    1. 25TB utiles de stockage, répliqués au fil de l'eau sur les deux clusters et dédiés aux utilisateurs (/home) moyennant quota de projets
    2. 98TB utiles servant d'espace de travail pour les jobs parallèles (/workdir), 49TB par cluster
    3. environ 56TB utiles totalisés servant d'espace de travail pour les jobs mono-noeuds
    4. 112TB d'archive dédiés à un usage uniquement d'archivage et moyennant quota de projets (l'utilisation de fichiers compressés (.tar.gz) serait grandement apprécié)

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.


Commandes utiles -en bref- pour la gestion des jobs

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.


Exemple de script pour un job sequentiel

#!/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>


Demande de ressources

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:

  1. walltime: le nombre d'heures pendant lequel votre calcul est autorisé a tourner. Au delà, le job serait tué par le système. Valeur par défaut: 1 heure.
  2. nodes: le nombre de noeuds sur lesquels vous souhaitez voir s'exécuter votre job.
  3. ppn: nombre de processeurs: votre calcul aura à disposition, par noeud, le nombre de processeurs désigné. Vous pouvez demander un certain nombre de noeuds (défaut: 1) ainsi qu'un certain nombre de processeurs par noeuds (défaut: 1)


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


Lancer des jobs interactifs

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


Lancer des jobs MPI

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


Partitionnement du cluster

Le cluster Hades (technologie Intel) est principalement composé de deux types de serveurs de calcul (voir Environnement matériel):

  1. des noeuds avec 12 coeurs et 4GB/core (Dell PowerEdge c6100, bi-pro Intel Xeon X5650, 48GB de RAM): node001 à node018 et node027 à node029
  2. des noeuds avec 12 coeurs et 2GB/core (SuperMicro 6026TT, bi-pro Intel Xeon X5650, 24GB de RAM): node019 à node026
    1. un noeud avec 8 coeurs et 5GB/core (Dell PowerEdge c6100, bi-pro Intel Xeon X5560, 40GB de RAM): node030

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 :

  1. des noeuds avec 32 coeurs et 1GB/core (SuperMicro 2022TG, bi-pro AMD Opteron 6282SE, 32GB de RAM): node031 à node046
  2. des noeuds avec 32 coeurs et 1GB/core (SuperMicro 2022TG, bi-pro AMD Opteron 6380, 32GB de RAM): node047 à node058
  3. 2 noeuds SMP avec 24 coeurs et ~3GB/core (SuperMicro, bi-pro Intel Xeon E5-2697v2, 64GB de RAM, 16TB RAID5): node059 à node060
  4. 2 noeuds GPU avec 16 coeurs et 4GB/core (SuperMicro, bi-pro Intel Xeon E5-2650v2, 64GB de RAM, 16TB RAID5 et 2 GPU NVidia GTX 780Ti): node061 à node062


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 :

  1. des noeuds node059 et node060 qui, eux, appartiennent à la queue monop adressable spécifiquement par l'option “-q monop” à qsub
  2. des noeuds node061 et node062 qui, eux, appartiennent à la queue gpu adressable uniquement par l'option “-q gpu” à qsub


Prologues et épilogues

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

Tableau de jobs

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

Utilisation "avancée"

Compilation de nouvelles applications/librairies

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.

Gestion des variables d'environnement

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.

Recommandation

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.