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.
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 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.