Clusters et pipelines avec LSF

pipelines
Pipe­lines Nick‑K (Nikos Kou­tou­las) (CC BY-NC 2.0)

Aujourd'hui petit mash-up de deux articles pré­cé­dem­ment publiés dans nos colonnes. Comme je l'avais pro­mis, je vais vous pré­sen­ter ma méthode pour faire du pipe­li­ning avec le ges­tion­naire de res­sources de notre clus­ter. Si vous n'avez pas com­pris la phrase pré­cé­dente, je vous invite à aller (re-)lire l'article sur les pipe­lines et celui sur les clus­ters, tout devrait être plus clair. Je vais pré­sen­ter une idée simple : com­ment iden­ti­fier cha­cune de vos com­mandes sur un clus­ter et uti­li­ser cette iden­ti­fi­ca­tion pour les lier dans un pipe­line. Les exemples de l'article sont basés sur le sys­tème de mana­ge­ment LSF, ins­tal­lé sur les clus­ters Vital-it du SIB. Bien qu'il existe des dif­fé­rences avec d'autres sys­tèmes, vous devriez retrou­ver ces fonc­tion­na­li­tés sur cha­cun d'entre eux.

Nommez vos commandes…

Comme vous le savez main­te­nant, avec un pipe­line, on sou­haite enchaî­ner dif­fé­rentes tâches sans avoir à inter­ve­nir. Il faut donc pou­voir dire quand la com­mande 'une' s'est ter­mi­née, pour lan­cer la 'deux'. Pour cela il faut pou­voir créer une chaîne entre nos dif­fé­rentes com­mandes et un bon moyen pour le faire est de toutes les iden­ti­fier.

Pour cela rien de plus simple. LSF pro­pose de don­ner un nom à vos com­mandes avec l'option '-J'.

bsub -J première 'ma première commande'
bsub -J deuxième 'ma deuxième commande'

Cette option est très utile et pas seulement pour faire des pipelines. Imaginez que vous ayez 100 fichiers à traiter et que vous utilisiez le cluster pour le faire. Si vous vous apercevez qu'il y a une erreur sur certaines de ces commandes, comment allez-vous pouvoir arrêter juste celles-ci ? Si elles n'ont pas de nom, vous n'avez plus qu'à chercher parmi les 100 commandes ou encore tout arrêter. Mais si vous avez utilisé l'option '-J' vous pouvez arrêter juste ces commandes. De plus avec le symbole '*' vous pouvez arrêter toutes les commandes avec le même morceau de nom.

bkill -J groupe_1_*

'bkill' est la commande LSF pour tuer un job et elle prend aussi l'option '-J'. Ici je tue toutes les commandes dont le nom commence par 'groupe_1_', on peut imaginer que j'ai un groupe 2 qui lui ne sera pas arrêté.

Bien, maintenant on sait donner un nom à nos commandes, mais LSF ne sait pas lire, du coup il faut lui dire quelle commande doit attendre l'autre.

...puis connectez-les.

<

p style="text-align: justify;">'bsub' a une autre option extrêmement utile : -w
Il s'agit en fait d'une option 'wait' et celle-ci est très bien pensée. Elle vous permet d'attendre qu'une autre commande soit terminée et même de vérifier si elle s'est bien achevée ou si une erreur s'est produite. Elle inclut aussi l'utilisation d'opérateurs logiques (and, or et not) pour pouvoir attendre la fin (ou le lancement) de plusieurs commandes.
Concrètement, il existe quatre conditions possibles : started, done, exit, ended.
Started teste si la commande s'est lancée, ended si elle s'est terminée. Pour 'done' et 'ended' je dois préciser que, sous GNU/Linux, chaque commande renvoie à la fin un code. 0 indique que tout s'est bien passé et toutes les autres possibilités correspondent à différentes erreurs. Si je crée une commande 1 puis une commande 2 avec la condition '-w done(1)' et une commande 3 avec la condition 'exit(1)'. La commande 2 sera exécutée seulement si la commande 1 se termine sans erreur et la commande 3 seulement si la commande 1 se termine avec une erreur. Il est même possible, avec 'exit', d'attendre un code d'erreur spécifique (1, 2 ou 3 …), ce qui permet de prévoir plusieurs réactions. Voici donc un exemple :

bsub -J messager -w "(done(groupe_1_*) || done(groupe_2_*)) && started(trieur)" 'commande envoyer message'

La commande 'messager' ne démarrera que si toutes les commandes dont le nom commence par 'groupe_1_' se sont bien terminées ou ('||') si toutes les commandes dont le nom commence par 'groupe_2_' se sont bien terminées et ('&&') que la commande 'trieur' a été lancée.

Et voila comment, avec les outils mis à disposition par le queuing système, on peut construire un pipeline. Il suffit ensuite de construire un script (en python par exemple) qui crée et nomme les commandes pour vous et vous obtenez un pipeline performant.

 

Ici je vous ai présenté une seule stratégie, elle n'est pas unique et n'est pas obligatoirement la meilleure. On pourrait aussi utiliser un fichier de log où les commandes notent quand elles commencent et quand elles se terminent et avoir un distributeur qui lit ce fichier pour savoir quand lancer la commande suivante. Les stratégies sont nombreuses et vous devez vous adapter à votre environnement et aux besoins de vos collègues.

Merci à Nelly, Yoann, Mica et Sp4M pour leur relecture.



Pour continuer la lecture :


Commentaires

Laisser un commentaire