Ordonnancement Slurm des tâches exécutées avec GPU

Revision as of 18:31, 27 November 2017 by FuzzyBot (talk | contribs) (Updating to match new version of source page)
Other languages:

Pour l'information générale sur l'ordonnancement des tâches, consultez Exécuter des tâches.

Nœuds disponibles

Le tableau suivant décrit les nœuds avec GPUs présentement disponibles avec Cedar et Graham.

# de nœuds Type de nœud Cœurs CPU Mémoire CPU # de GPUs Type de GPU Topologie du bus PCIe
114 GPU base, Cedar 24 128Go 4 NVIDIA P100-PCIE-12GB deux GPUs par socket CPU
32 GPU large, Cedar 24 256Go 4 NVIDIA P100-PCIE-16GB tous les GPUs associés au même socket CPU
160 GPU base, Graham 32 128Go 2 NVIDIA P100-PCIE-12GB un GPU par socket CPU

Tâches avec un seul cœur

Pour une tâche qui nécessite un seul cœur CPU et un GPU,

File : gpu_serial_job.sh

#!/bin/bash
#SBATCH --account=def-someuser
#SBATCH --gres=gpu:1              # Number of GPUs (per node)
#SBATCH --mem=4000M               # memory (per node)
#SBATCH --time=0-03:00            # time (DD-HH:MM)
./program


Tâches multifils

Pour une tâche GPU qui nécessite plusieurs CPUs dans un seul nœud,

File : gpu_threaded_job.sh

#!/bin/bash
#SBATCH --account=def-someuser
#SBATCH --gres=gpu:1              # Number of GPU(s) per node
#SBATCH --cpus-per-task=6         # CPU cores/threads
#SBATCH --mem=4000M               # memory per node
#SBATCH --time=0-03:00            # time (DD-HH:MM)
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
./program


Pour chaque GPU, les tâches multifils ne devraient pas dépasser

  • avec Cedar, 6 cœurs;
  • avec Graham, 16 cœurs.

Tâches MPI

File : gpu_mpi_job.sh

#!/bin/bash
#SBATCH --account=def-someuser
#SBATCH --gres=gpu:4              # Number of GPUs per node
#SBATCH --nodes=2                 # Number of nodes
#SBATCH --ntask=48                # Number of MPI process
#SBATCH --cpus-per-task=1         # CPU cores per MPI process
#SBATCH --mem=120G                # memory per node
#SBATCH --time=0-03:00            # time (DD-HH:MM)
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
srun ./program


Nœuds entiers

Si votre application peut utiliser efficacement un nœud entier et ses GPUs associés, vous pouvez probablement réduire le temps d'attente si vous demandez un nœud entier. Utilisez les scripts suivants comme modèle.

Ordonnancement d'un nœud GPU pour Graham

File : graham_gpu_node_job.sh

#!/bin/bash
#SBATCH --nodes=1
#SBATCH --gres=gpu:2
#SBATCH --ntasks-per-node=32
#SBATCH --mem=128000M
#SBATCH --time=3:00
#SBATCH --account=def-someuser
nvidia-smi


Ordonnancement d'un nœud GPU pour Cedar

File : cedar_gpu_node_job.sh

#!/bin/bash
#SBATCH --nodes=1
#SBATCH --gres=gpu:4
#SBATCH --exclusive
#SBATCH --mem=125G
#SBATCH --time=3:00
#SBATCH --account=def-someuser
nvidia-smi


Ordonnancement d'un nœud GPU large pour Cedar

Sur la grappe Cedar se trouvent des nœuds de type GPU large qui ont chacun quatre cartes Tesla P100 16Go, alors que les autres nœuds sont de 12Go. Les nœuds de type GPU large utilisent le même connecteur PCI, ce qui fait que la latence dans les communications entre GPUs est plus faible; cependant, la bande passante entre CPUs et GPUs est plus basse que dans le cas des nœuds GPU réguliers. De plus, la mémoire vive des nœuds est de 256Go plutôt que de 128Go. Pour utiliser ces nœuds, il faut demander des nœuds entiers et indiquer lgpu. Les tâches avec GPU ont un temps d'exécution maximal de 24 heures. Il peut arriver que des tâches GPU courtes soient exécutées sur ces nœuds par remplissage (backfilling) si aucune tâche pour nœud entier n'est en attente.


File : large_gpu_job.sh

#!/bin/bash
#SBATCH --nodes=1 
#SBATCH --gres=gpu:lgpu:4   
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=24    # There are 24 CPU cores on Cedar GPU nodes
#SBATCH --time=3:00
#SBATCH --account=def-someuser
hostname
nvidia-smi


Regroupement de tâches pour un seul GPU

Pour exécuter pendant plus de 24 heures quatre programmes qui utilisent un seul GPU ou deux programmes qui utilisent deux GPUs, nous recommandons GNU Parallel. Voici un exemple simple :

cat params.input | parallel -j4 'CUDA_VISIBLE_DEVICES=$(({%} - 1)) python {} &> {#}.out'

L'identifiant du GPU est calculé en soustrayant 1 de l'identifiant de la fente (slot), représenté par {%}. L'identifiant de la tâche est représenté par {#}, avec des valeurs partant de 1.

Le fichier params.input devrait contenir les paramètres sur des lignes distinctes, comme suit :

code1.py
code2.py
code3.py
code4.py
...

Vous pouvez ainsi soumettre plusieurs programmes. Dans ce cas, GNU Parallel exécutera jusqu'à quatre tâches concurremment et lancera une tâche aussitôt que la précédente sera terminée. Pour éviter que deux programmes se disputent le même GPU, utilisez CUDA_VISIBLE_DEVICES.