Sommaire
Premiers pas avec l'environnement Pangeo
Pangeo se définit comme une plateforme communautaire pour le Big Data en Géoscience. Les chercheurs impliqués dans le projet Pangeo ont décidé de s'appuyer sur des paquetages python comme Dask, Xarray et Iris avec Jupyter comme interface de programmation.
Dans la suite de cette page, nous n'entrerons pas dans les détails du fonctionnement des paquetages Dask et Jupyter Notebook mais fournissons les étapes minimales pour obtenir un environnement de travail Dask déployé en mode Cluster distribué Dask.distributed à l'aide de Dask-Jobqueue.
1. Activer l'environnement Pangeo sur Summit2
S'assurer que la commande conda est disponible sur Summit2 (voir environnement conda)
Vérifier que l'environnement pangeo-env_summit2 est présent :
conda info -e
Activer l'environnement avec :
conda activate pangeo-env_summit2
Créer le fichier de configuration de Jupyter notebook avec :
jupyter notebook --generate-config
Créer un mot de passe pour Jupyter notebook avec :
jupyter notebook password
(pangeo-env_summit2) gazdi@summit2:~> jupyter notebook password Enter password: Verify password: [NotebookPasswordApp] Wrote hashed password to /home/gazdi/.jupyter/jupyter_notebook_config.json
Créer un répertoire de travail pangeo :
mkdir pangeo
2. Travailler sur UN nœud de calcul
Cette section décrit comment utiliser un nœud de calcul pour travailler sous Dask. Elle s'inspire de la documentation dask.distributed on a single machine.
Créer le script pour le lancement du serveur Jupyter Lab sur un nœud de calcul :
cd pangeo vi job_monojupyter.sh
et y copier les lignes ci-dessous :
#!/bin/bash # #SBATCH -N1 --exclusive #SBATCH -e monojupyter-%j.out #SBATCH -o monojupyter-%j.out source /home/sila/miniconda3/etc/profile.d/conda.sh conda deactivate conda activate pangeo-env_summit2 jupyter lab --no-browser --ip=`hostname` --port=8888
Soumettre le job avec sbatch en spécifiant la partition Slurm, par exemple any :
sbatch -p any job_monojupyter.sh
gazdi@summit2:~/pangeo> sbatch -p any job_monojupyter.sh Submitted batch job 4945731
Repérer sur quel nœud s'exécute le job avec :
squeue -u $USER
gazdi@summit2:~/pangeo> squeue -u $USER JOBID PARTITION NAME USER ST TIME NODES CPUS NODELIST(REASON) 4945731 any job_mono gazdi R 0:04 1 8 n405Ouvrir une fenêtre terminal sur VOTRE PC et exécuter la commande :
ssh -N -L8888:nX:8888 summit2
en remplaçant nX par le numéro du nœud identifié précédemment sur lequel s'exécute Jupyter Lab, par exemple pour l'utilisateur gazdi travaillant sur aeropc98 :
gazdi@aeropc98:~> ssh -N -L8888:n405:8888 summit2 bind: Cannot assign requested address
Noter que le prompt n'apparaît pas après la saisie de la commande et qu'une ou plusieurs lignes 'bind: Cannot assign requested address' s'affichent : c'est normal !
Mettre cette fenêtre de côté, elle assure la redirection du port 8888 sur le nœud où s'exécute Jupyter Lab (indispensable pour l'étape suivante).Lancer un navigateur Web sur VOTRE PC, puis saisir l'adresse ci-dessous :
http://localhost:8888/
qui ouvre un Jupyter Notebook sur la page de login. Saisir alors le mot de passe défini au dessus.Ouvrir un notebook Python 3, et saisir le code python ci-dessous dans une cellule :
from dask.distributed import Client, LocalCluster cluster = LocalCluster() cluster
A l'exécution de la cellule un widget doit s'afficher indiquant LocalCluster avec 8 processus worker occupant les 8 cores du nœud n405 dans cet exemple.
Après avoir instancié la classe Client dans une nouvelle cellule :
client = Client(cluster)il est possible de manipuler les différentes interfaces utilisateurs de Dask (voir Dask User Interfaces), par exemple avec :
import dask.array as da x = ... # Dask commands now use these distributed resources
Se rendre à la section Dashboard Dask pour poursuivre le test.
3. Travailler avec plusieurs nœuds de calcul
Dans ce mode, lancer Jupyter Lab sur un nœud comme précédemment et utiliser le module python dask_jobqueue pour démarrer des jobs workers comme indiqué dans la documentation dask_jobqueue.
Pour démarrer un processus worker par nœud qui exploite tous les cœurs et toute la mémoire du nœud sans avoir à se préoccuper du type de nœud au sein d'une même partition, il est préférable d'utiliser le module summit2_jobqueue spécialement écrit pour Summit2 (voir section Module summit2_jobqueue).
Pour des raisons de performance et de bon fonctionnement, choisir une partition Slurm qui vérifie ces 2 contraintes :
partition avec des nœuds équipés de cartes IB, de manière à ce que les workers communiquent via l'interface réseau rapide ib0
partition qui ne s'étend pas sur plusieurs armoires (cas de la partition any par exemple) car les réseaux IB de chaque armoire sont indépendants.
Partitions possibles : mpib40_SIRO mpib40_POM mpib40_B0 mpib40_MESO mpib40_B1 o3piasiib fuxi_* edi_15IB pom16ib crocoib
Préparer un job Jupyter Lab : A la différence de la section précédente, le nœud n'est pas entièrement alloué, de manière à pouvoir éventuellement accueillir un ou plusieurs workers Dask :
cd pangeo vi job_jupyter.sh
et copier les lignes suivantes :
Noter que le nombre de cpus alloués (fixé à 2 dans l'exemple) est une indication (peut-être vaut-il mieux prendre tout le nœud ?)#!/bin/bash # #SBATCH -p fuxi_debug #SBATCH -c2 #SBATCH -n1 #SBATCH -e jupyter-%j.out #SBATCH -o jupyter-%j.out source /home/sila/miniconda3/etc/profile.d/conda.sh conda deactivate conda activate pangeo-env_summit2 jupyter lab --no-browser --ip=`hostname` --port=8888
Soumettre le job avec sbatch :
sbatch job_jupyter.sh
gazdi@summit2:~/pangeo> sbatch job_jupyter.sh Submitted batch job 4946330
Repérer sur quel nœud s'exécute le job avec :
squeue -u $USER
gazdi@summit2:~/pangeo> squeue -u $USER JOBID PARTITION NAME USER ST TIME NODES CPUS NODELIST(REASON) 4946469 fuxi_debug job_jupy gazdi R 1:11:55 1 2 n208Ouvrir un autre terminal sur VOTRE PC et exécuter la commande :
ssh -N -L8888:n208:8888 summit2
Par exemple :
gazdi@aeropc98:~> ssh -N -L8888:n208:8888 summit2 bind: Cannot assign requested address
Noter que le prompt n'apparaît pas après la saisie de la commande et qu'une ou plusieurs lignes 'bind: Cannot assign requested address' s'affichent : c'est normal !
Mettre cette fenêtre de côté, elle assure la redirection du port 8888 sur le nœud où s'exécute Jupyter Lab (indispensable pour l'étape suivante).Lancer enfin un navigateur Web sur VOTRE PC et saisir l'adresse ci-dessous :
http://localhost:8888/
qui ouvre Jupyter Notebook sur la page de login. Saisir alors le mot de passe défini au dessus.
3.1. Module dask_jobqueue
Ouvrir un notebook Python 3, et saisir le code python ci-dessous dans une cellule :
from dask_jobqueue import SLURMClusterNoter qu'à la toute première exécution de l'import ci-dessus, un fichier de configuration jobqueue.yaml est copié dans le répertoire $HOME/.config/dask/ de l'utilisateur. Il contient une liste d'options commentées pour l'ensemble des gestionnaires de ressources (comme Slurm, PBS, ...) pris en charge par le module dask_jobqueue (voir configuration dask_jobqueue). Sur Summit2 qui fonctionne sous Slurm, son contenu peut être remplacé par celui-ci :
# FILE : $HOME/.config/dask/jobqueue.yaml jobqueue: slurm: name: dask-worker # Dask worker options cores: 8 # Total number of cores per job memory: '24 GB' # Total amount of memory per job processes: 1 # Number of Python processes per job (number of worker process) interface: ib0 # Network interface to use like eth0 or ib0 death-timeout: 60 # Number of seconds to wait if a worker can not find a scheduler local-directory: '/workdir/$USER' # Location of fast local storage like /scratch or $TMPDIR # SLURM resource manager options queue: fuxi_debug project: null walltime: '01:30:00' extra: [] env-extra: [] job-cpu: null job-mem: null job-extra: ['-e daskworker-%j.out','-o daskworker-%j.out'] log-directory: nullLes options définis dans le fichier ci-dessus forment les options par défaut de la classe SLURMCluster et définissent les caractéristiques d'un job Slurm pour lancer un ou plusieurs processus worker Dask. Ces valeurs peuvent être modifiées lors de l'instanciation de la classe comme dans le code python ci-dessous à saisir dans une nouvelle cellule de Jupyter Lab :
cluster=SLURMCluster(cores=2, memory='6 GB', processes=1, interface='ib0', queue='fuxi_debug', )
La commande ci-dessus définit un job qui allouera 2 cpus (cores=2) dans la partition fuxi_debug et lancera un seul processus worker (processes=1) qui utilisera les 2 cpus avec 3GB/cpu (memory=6GB). L'interface réseau sélectionnée pour la communication entre les processus worker et le scheduler Dask est de type infiniband (interface='ib0'). Noter que l'instanciation ne lance aucun job sur le cluster. Pour vérifier le contenu du job qui sera lancé ultérieurement, exécuter la commande suivante dans une nouvelle cellule de Jupyter Lab :
print(cluster.job_script())
Pour véritablement lancer des jobs worker utiliser la méthode scale de la classe SLURMCluster en spécifiant le nombre de processus worker à démarrer. Dans l'exemple ci-dessous, 4 jobs sont soumis (car 1 job lance 1 processus worker) en exécutant la cellule suivante :
cluster.scale(4)
Avec cluster=SLURMCluster(...,processes=2,...), un job worker est configuré pour lancer 2 processus worker.
La commande cluster.scale(4) ne démarre alors que 2 jobs worker soit un total de 4 processus worker. En effet, l'argument X dans cluster.scale(X) designe le nombre de processus worker (et non pas le nombre de jobs) !
Il est possible également de lancer des processus worker de manière interactive via les widgets ipython en affichant le contenu de la variable cluster. Exécuter simplement une cellule Jupyter Lab dans lequel vous avez saisi la variable cluster :
cluster
A l'exécution de la cellule un widget doit s'afficher indiquant SLURMCluster avec 4 processus worker occupant 8 cores et 24GB Ram du nœud n208 dans cet exemple. En ouvrant 'Manual scaling', il est possible d'ajuster de manière interactive le nombre de workers en cliquant sur 'Scale'.
Pour vérifier que de nouveaux jobs ont été lancés, exécuter la commande 'squeue' dans un terminal sur Summit2 :
gazdi@summit2:~> squeue -u $USER JOBID PARTITION NAME USER ST TIME NODES CPUS NODELIST(REASON) 4946477 fuxi_debug dask-wor gazdi R 0:02 1 2 n208 4946478 fuxi_debug dask-wor gazdi R 0:02 1 2 n208 4946479 fuxi_debug dask-wor gazdi R 0:02 1 2 n208 4946480 fuxi_debug dask-wor gazdi R 0:02 1 2 n208 4946469 fuxi_debug job_jupy gazdi R 1:16:20 1 2 n208 gazdi@summit2:~>A cette étape, il est possible de manipuler les différentes interfaces utilisateurs de Dask (voir Dask User Interfaces) :
from dask.distributed import Client client = Client(cluster) # Connect this local process to remote workers # wait for jobs to arrive, depending on the queue, this may take some time import dask.array as da x = ... # Dask commands now use these distributed resources
Se rendre à la section Dashboard Dask pour poursuivre le test.
3.2. Module summit2_jobqueue
Récupérer le source du module summit2_jobqueue.py et le placer dans le répertoire d'où est lancé Jupyter Lab ou un répertoire pointé par la variable d'environnement PYTHONPATH.
Ce module est une adaptation du module dask_jobqueue. Il permet de simplifier l'instanciation de la classe SLURMCluster tout en configurant par défaut un job worker de la manière suivante :
- - un seul worker/job
- - un seul job/nœud (mode exclusive de Slurm)
- - tous les cpus du nœud alloués pour le job et disponibles pour le processus worker
- - toute la mémoire du nœud est disponible pour le processus worker
Le principe d'utilisation est identique à précédemment, Il faut toutefois modifier le fichier 'jobqueue.yaml' puis simplement changer la ligne d'import de la classe SLURMCluster comme détaillé ci-dessous.
Ajouter dans le fichier $HOME/.config/dask/jobqueue.yaml, la section summit2 :
# FILE : $HOME/.config/dask/jobqueue.yaml jobqueue: slurm: name: dask-worker # Dask worker options cores: 8 # Total number of cores per job memory: '24 GB' # Total amount of memory per job processes: 1 # Number of Python processes per job (number of worker process) interface: ib0 # Network interface to use like eth0 or ib0 death-timeout: 60 # Number of seconds to wait if a worker can not find a scheduler local-directory: '/workdir/$USER' # Location of fast local storage like /scratch or $TMPDIR # SLURM resource manager options queue: fuxi_debug project: null walltime: '01:30:00' extra: [] env-extra: [] job-cpu: null job-mem: null job-extra: ['-e daskworker-%j.out','-o daskworker-%j.out'] log-directory: nullsummit2: name: dask-worker # Dask worker options cores: 0 # Total number of cores per job (0 for all cores) memory: '0 GB' # Total amount of memory per job (0 for all memory) processes: 1 # Number of Python processes per job interface: ib0 # Network interface to use like eth0 or ib0 death-timeout: 60 # Number of seconds to wait if a worker can not find a scheduler local-directory: '/workdir/$USER' # Location of fast local storage like /scratch or $TMPDIR # SLURM resource manager options queue: fuxi_debug project: null walltime: '01:30:00' extra: [] env-extra: [] job-cpu: null job-mem: null job-extra: ['-e daskworker-%j.out','-o daskworker-%j.out'] job-extra: [] log-directory: nullSoumettre un job Jupyter Lab et ouvrir un navigateur avec Jupyter Notebook comme indiqué ci-dessus.
Exécuter dans une cellule la ligne suivante :
from summit2_jobqueue import SLURMClusterAfficher le contenu du job slurm pour le processus worker en exécutant dans une cellule :
cluster=SLURMCluster() print(cluster.job_script())
Démarrer des jobs worker avec :
cluster.scale(4)
ou par le widget SLURMCluster qui apparaît en exécutant :
cluster
Vérifier la création des jobs avec squeue -u $USER dans une fenêtre sur Summit2 :
gazdi@summit2:~> squeue -u $USER JOBID PARTITION NAME USER ST TIME NODES CPUS NODELIST(REASON) 4946532 fuxi_debug dask-wor gazdi PD 0:00 1 1 (Resources) 4946533 fuxi_debug dask-wor gazdi PD 0:00 1 1 (Priority) 4946498 fuxi_debug dask-wor gazdi R 9:19 1 8 n211 4946499 fuxi_debug dask-wor gazdi R 9:19 1 20 n209 4946469 fuxi_debug job_jupy gazdi R 5:07:32 1 2 n208A cette étape, il est possible de manipuler les différentes interfaces utilisateurs de Dask (voir Dask User Interfaces) :
from dask.distributed import Client client = Client(cluster) # Connect this local process to remote workers # wait for jobs to arrive, depending on the queue, this may take some time import dask.array as da x = ... # Dask commands now use these distributed resources
4. Dashboard de Dask
Le dashboard est disponible dès que les classes SLURMCluster ou LocalCluster ont été instanciées. Pour accéder à la page Dask dashboard lorsque vous travaillez avec JupyterLab, ouvrir un nouvel onglet dans le navigateur Web et saisir l'adresse :
http://localhost:8888/proxy/8787/status
Naviguer sur les différents onglets de la page pour afficher diverses informations sur les processus workers. Pour plus d'informations, voir la documentation Diagnostics Dashboard et Web Interface.
Si vous ne travaillez pas sous JupyterLab/Notebook mais directement avec python ou Ipython :
Ouvrir une fenêtre terminal sur VOTRE PC et exécuter la commande :
ssh -N -L8787:nX:8787 summit2
en remplaçant nX par le numéro du nœud alloué pour travailler.
Lancer un navigateur Web sur VOTRE PC, puis saisir l'adresse ci-dessous :
http://localhost:8787/status
5. Terminer la session Jupyter Lab
Pour tuer tous les processus worker (et terminer les jobs correspondants) :
mettre à 0 le nombre de workers et cliquer sur 'Scale' dans le widget ou bien exécuter une cellule contenant la ligne :
cluster.scale(0)
Fermer Jupyter Notebook proprement en cliquant sur le menu File/quit de la fenêtre JupyterLab
Vérifier avec squeue -u $USER que le job 'job_jupyter' a bien disparu
Stopper avec CTRL-C la commande ssh de redirection du port 8888 lancée sur VOTRE PC
