Envío de trabajos#

Clementina XXI usa Slurm como sistema de job scheduling.

Comandos básicos#

sbatch <script.sh> se usa para enviar un job script que encolará un job en la queue. El script puede contener comandos srun para lanzar tareas paralelas.

scancel <job_id> se usa para cancelar un trabajo pendiente o en ejecución.

sinfo reporta el estado de las particiones y los nodos manejados por Slurm. Tiene una gran variedad de opciones de filtrado, ordenamiento y formateo.

squeue reporta el estado de los trabajos. Tiene gran variedad de opciones de filtrado, ordenamiento y formateo. Reporta los trabajos corriendo (running) en orden de prioridad y luego los trabajos pendientes en orden de prioridad.

squeue # todos
squeue -A account   # por cuenta
squeue -u usuario   # por usuario

Nota

Cada comando tiene su propia man page, por ejemplo, man sbatch. El comando --help también provee un sumario de opciones. Notar que los comandos son case sensitive.

Particiones#

Contamos con 4 particiones:

  • cpunode: Utilizar para trabajos que únicamente utilizan cómputo mediante CPU.

  • gpunode: Utilizar para trabajos que requieren utilizar cómputo mediante GPU.

  • testing: Partición de pruebas (tanto CPU como GPU) con un máximo de 20 minutos de uso. Usar esta partición para comprobar si los inputs que quiere utilizar funcionan correctamente. Haga un uso responsable de esta partición ya que es un recurso limitado.

  • batch: Partición por default. Es la partición que se asigna cuando no se especifica partición de manera explícita. Existe por razones de soporte. Evite usarla explícitamente ya que la misma puede ser eliminada en el futuro.

Exceptuando la partición de testing, el resto tiene un tiempo máximo de 48hs por job.

Envío en modo sbatch#

Se aconseja utilizar scripts para automatizar, documentar, y replicar correctamente los trabajos que enviamos al cluster via Slurm.

Las directivas de Slurm comienzan con #SBATCH. El comando sbatch ejecuta las directivas y las envía a Slurm, y deja de procesarlas al llegar a la primer linea que no sea ni un comentario ni una linea en blanco.

Luego de eso los comandos del script se ejecutan en los nodos de cómputo como si se tratara de un script de bash.

Ejemplo#

Advertencia

Es crucial usar la flag --time para especificar una heurística de cuánto se estima que va a tardar el job. Si no se especifica, el scheduler asume que el tiempo de ejecución es el máximo de la partición y puede llevar a mayores tiempo de espera en cola.

Nota

Este ejemplo (sin la directiva de account) y todos sus archivos se encuentran disponibles en /data/shared/examples/slurm-hello-world/.

A modo de ejemplo, puede considerarse un job en cual se imprime por pantalla un hello world por cada proceso. Para esto es necesario crear el archivo hello_world.job, con los siguientes contenidos

#!/bin/bash
#SBATCH --account=<pad|pci|pisca>_<id_ipac>
#SBATCH --job-name=hello_world
#SBATCH --output=hello_world_%j.out ##%j: job id
#SBATCH --error=hello_world_%j.err
#SBATCH --ntasks-per-node=64 ## se usan los 64 procesos
#SBATCH --partition=gpunode
#SBATCH --time=00:10:00

# Carga de módulos correspondientes
module purge
module load intel openmpi4

# Compilación, en caso de que sea necesario
mpicc mpi_hello_world.c -o mpi_hello_world

# Ejecución con el número de tareas especifcado en --ntasks-per-node
mpirun ./mpi_hello_world

El nombre de la account depende del tipo de IPAC y el número del proyecto correspondiente. Por ejemplo, para el PAD número 70 es pad_70, para el PCI número 60 es pci_60 y para el PISCA número 65 es pisca_65.

Para enviar el trabajo, se ejecuta:

sbatch hello_world.job

en el mismo directorio en el que se encuentra mpi_hello_world.c.

Puede monitorearse la posición del trabajo en la cola con el comando squeue. También se pueden ver solo los trabajos propios con squeue --me.

Una vez que el programa comienza a ejecutarse, la salida se escribe en los archivos indicados por #SBATCH --output y #SBATCH --error (stdout y stderr, respectivamente).

Nota

Para ver todas las opciones para configurar los trabajos que ofrece SLURM, vea la documentación de SLURM.

Notificaciones de jobs via mail#

Se puede solicitar a slurm que notifique via mail los eventos de inicio, finalización, falla, o requeue de su job. Se deben definir el evento a notificar y la dirección de mail de la siguiente manera:

#SBATCH --mail-type=ALL
#SBATCH --mail-user=user@example.com

Los tipos válidos para mail-type son BEGIN, END, FAIL, REQUEUE, o ALL para todos los eventos.

Hold/Release de jobs#

Para postergar la asignación de un job en estado PENDING:

scontrol hold 5975   # por job ID
scontrol release 5975   # permitir que sea programado para comenzar. 

Fair Share#

Al momento de asignar un recurso libre, el scheduler determinará la prioridad de los jobs en base a una cuota de uso que tiene cada usuario. Esta cuota dependerá de un valor inicial de shares que tiene cada usuario, las cuotas asignadas a su respectiva account, la cantidad de horas/cómputo que el usuario ha consumido en el último período de tiempo, y la partición seleccionada para el job.

Se puede monitorear con el comando sshare.

sshare -a           # todos los usuarios
sshare -u user      # share del usuario
sshare -A account   # share de la account

Nota

Para más información sobre cómo funciona el algoritmo de Fair Share, vea la documentación de SLURM.

Nota

Para consultas sobre la prioridad de los trabajos, vea las preguntas frecuentes.

Envío en modo interactivo#

Advertencia

El envío de jobs de manera interactiva consume horas de cómputo al igual que cualquier otro job. Si no se pone un límite de tiempo a una corrida interactiva y se deja desatendida, consumirá horas hasta el límite de tiempo impuesto por la cola (p.ej. 48hs por cada core reservado).

También es posible correr trabajos en modo interactivo, que puede ser preferible para pruebas de funcionamiento, compilación de programas, etc. Para pedir los recursos, se utiliza el comando srun. Por ejemplo, para reservar por diez minutos un nodo de 64 cores con 4 GPUs, se ejecuta

[user@snmgt01] srun --time=00:10:00 --gpus=4 -n 64 --account=<pad|pisca|pci>_<id ipac> --pty /bin/bash 
[user@cn001] # Terminal en nodo de cómputo
[user@cn001] exit
[user@snmgt01] # Terminal en nodo de login

Es crucial salir del nodo de cómputo con exit (o CTRL-D) para que se dejen de contabilizar las horas utilizadas.

Job Arrays#

En el caso de necesitar correr múltiples jobs similares (p.ej. que corren el mismo programa con distintos inputs) o dependencias entre jobs, es útil usar job arrays.

Por ejemplo, si se tiene el job:

#SBATCH --job-name=multijobs
#SBATCH --nodes=1
#SBATCH --ntasks=1
#SBATCH --time=00:01:00
#SBATCH --partition=testing

ml purge

sleep 30
echo "Este job es parte de un array con el id interno $SLURM_ARRAY_TASK_ID"

y se envía con

JOBID=$(sbatch --parsable --array=1-3 multijobs.job) # O --array=1,2,3 para especificar los IDs manualmente

El job está compuesto por tres elementos: _1, _2 y _3 que van a imprimir algo distinto a pantalla, porque dependen de SLURM_ARRAY_TASK_ID (en este caso, 1, 2 y 3). En un job de producción, se puede elegir el input en base al valor de SLURM_ARRAY_TASK_ID.

Para correr un job 4 que es idéntico a los anteriores, pero depende de que terminen 1, 2 y 3 se puede enviar con la flag que indica la documentación de Slurm:

 sbatch --array=4 --depend=afterok:$JOBID multijobs.job # En este caso el mismo job, pero depende de que terminen los primeros 3.

Entonces, si se ejecuta ejecuto squeue voy a tener, al principio:

squeue --me
             JOBID PARTITION     NAME     USER ST       TIME  NODES NODELIST(REASON)
         JOBID_[4]   testing    first  user    PD       0:00      1 (Dependency)
         JOBID_1     testing    first  user     R       0:26      1 cn062
         JOBID_2     testing    first  user     R       0:26      1 cn062
         JOBID_3     testing    first  user     R       0:26      1 cn062

Los tres primeros elementos del job array están corriendo en simultáneo, cada uno en un core. Sin embargo, el job JOBID_[4] no puede entrar aunque haya recursos disponibles, porque depende de que los otros terminen sin error (eso significa --depend=afterok, y squeue lo indica con «(Dependency)»). Una vez que el primer job array termina, inmediatamente empieza el job array dependiente. Es decir, primero terminan los jobs 1, 2 y 3 y luego empieza a correr el job 4. Los resultados de 1, 2 y 3 van a estar disponibles antes de que el job 4 empiece.