⏲️ Slurm signals#
Una situación común es que un job se quede sin tiempo y SLURM lo cancele abruptamente, sin oportunidad de guardar el estado o escribir algun mensaje.
Para evitar este corte repentino, SLURM permite configurar el envío automático de señales
a los procesos antes de que se cumpla el tiempo límite.
Esta funcionalidad se puede aprovechar para implementar un graceful shutdown:
una finalización controlada del trabajo que permita, por ejemplo,
guardar el progreso, generar un checkpoint, copiar archivos del scratch
al home
, etc.
A continuación un ejemplo de juguete para ser adaptado.
Programa de ejemplo#
Primero necesitamos un programa que haga cómputo. Para simplificar el ejemplo, vamos a usar el siguiente script que simula hacer cálculos por 200 segundos.
1#!/bin/bash
2
3function sig_handler() {
4 echo "$(date +"%H:%M:%S"): pid=$$: Executable interrupted, task=$SLURM_PROCID"
5 exit 2
6}
7
8trap 'sig_handler' SIGTERM
9
10echo $(date +"%H:%M:%S"): pid=$$: BEGIN form $(hostname)
11sleep 200 &
12wait
13echo $(date +"%H:%M:%S"): pid=$$: END form $(hostname)
La función
sig_handler
simplemente imprime un log si el proceso es cancelado.
Script de submit#
El script va a llamar a nuestro programa,
cuando éste termine, llama a la función save_results
que simula guardar el resultado.
SBATCH --time
: 10 minutos de límite, y el signal se lanza a los pocos segundos (a los 5 segundos, pero en la práctica no es exacto)SBATCH --signal
: Configura la señal que enviará SLURM:SIGTERM
: Signal Terminate, solicita amablemente al proceso que termine.@595
: Cuantos segundos antes del límite se tiene que enviar la señal (9m55s).B:
: Si agregamos esto, la señal va al script. Sin esto, la señal va directamente al programa (ejecutado con srun).
srun
es bloqueante, por lo que cuando todas las tasks terminen o se cancelen, se va a llamar asave_results
.
1#!/bin/bash
2#SBATCH --partition=short
3#SBATCH --nodes=2
4#SBATCH --ntasks-per-node=1
5## Format: days-hours:minutes
6#SBATCH --time=0-0:10
7## Format: sig_num@time-in-seconds
8#SBATCH --signal=SIGTERM@595
9
10. /etc/profile
11
12function save_results {
13 echo $(date +"%H:%M:%S"): Saving results
14
15 for i in {0..100..10}
16 do
17 echo $(date +"%H:%M:%S"): Saving progress $i%...;
18 sleep 10;
19 done
20
21 echo $(date +"%H:%M:%S"): Results saved
22}
23
24echo $(date +"%H:%M:%S"): Calling srun from $(hostname)
25
26srun work.sh
27save_results
28
29echo $(date +"%H:%M:%S"): End of script
Ejemplo de salida#
Podemos ver que el srun se ejecuta en el primer nodo.
work.sh atrapa la señal e imprime su log.
El exit code 2 confirma que el job terminó por la signal.
El «proceso de guardado» corre por 100 segundos.
12:37:02: Calling srun from ivb14.ivb.ccad.unc.edu.ar
12:37:02: pid=713874: BEGIN form ivb14.ivb.ccad.unc.edu.ar
12:37:02: pid=351777: BEGIN form ivb15.ivb.ccad.unc.edu.ar
slurmstepd: error: *** STEP 1052540.0 ON ivb14 CANCELLED AT 2024-06-04T12:37:04 ***
12:37:04: pid=713874: Executable interrupted, task=0
12:37:04: pid=351777: Executable interrupted, task=1
srun: error: ivb14: task 0: Exited with exit code 2
srun: error: ivb15: task 1: Exited with exit code 2
12:37:05: Saving results
12:37:05: Saving progress 0%...
12:37:15: Saving progress 10%...
12:37:25: Saving progress 20%...
12:37:35: Saving progress 30%...
12:37:45: Saving progress 40%...
12:37:55: Saving progress 50%...
12:38:05: Saving progress 60%...
12:38:15: Saving progress 70%...
12:38:25: Saving progress 80%...
12:38:35: Saving progress 90%...
12:38:45: Saving progress 100%...
12:38:55: Results saved
12:38:55: End of script
Si el programa terminal antes, el output tiene la siguiente pinta:
13:10:44: Calling srun from rome52.rome.ccad.unc.edu.ar
13:10:44: pid=1880296: BEGIN form rome52.rome.ccad.unc.edu.ar
13:10:45: pid=1880296: END
13:10:46: pid=1433777: BEGIN form rome53.rome.ccad.unc.edu.ar
13:10:47: pid=1433777: END
13:10:47: Saving results
13:10:47: Saving progress 0%...
13:10:57: Saving progress 10%...
13:11:07: Saving progress 20%...
13:11:17: Saving progress 30%...
13:11:27: Saving progress 40%...
13:11:37: Saving progress 50%...
13:11:47: Saving progress 60%...
13:11:57: Saving progress 70%...
13:12:07: Saving progress 80%...
13:12:17: Saving progress 90%...
13:12:27: Saving progress 100%...
13:12:37: Results saved
13:12:37: End of script