3. Ejecucion de trabajos

Magerit se explota mediante trabajos batch usando SLURM como gestor y planificador de recursos. Para ejecutar se indican las características del trabajo que se necesita y el sistema se encargará de reservar los recursos necesarios y ejecutar las tareas.

3.1. Uso básico

El trabajo mínimo para ejecutar sería un fichero job.sh con el contenido:

1
2
3
4
5
#!/bin/bash

module purge && module load <app>

srun <app> --app-param app_args

El trabajo se envía al sistema ejecutando sbatch job.sh y ejecutaría 1 tarea (1 CPU) durante un máximo de 24 horas. Estos parámetros se pueden se puede modificar mediante directivas de SLURM.

Importante

Aunque las directivas se pueden especificar como argumentos de sbatch en el momento de enviar el trabajo, se recomienda definir las ejecuciones en ficheros para permitir su seguimiento.

Slurm proporciona una serie de mandatos que permiten controlar los trabajos en ejecución:

sbatch
Envía un trabajo al sistema devolviendo su identificador.
squeue
Lista los trabajos encolados en el sistema (aquellos que están ejecutando o esperando para ejecutar).
scancel
Cancela un trabajo encolado. Si el trabajo ya estaba ejecutando se abortará la ejecución en ese momento.
sstat
Muestra estadísticas de uso de un trabajo que esté ejecutando en ese momento.
sacct
Muestra información de la ejecución de un trabajo ya finalizado.

3.2. Definición de trabajos

Las directivas de SLURM son comentarios que empiezan con #SBATCH seguido de las mismas opciones que se indicarían a sbatch.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
#!/bin/bash
##----------------------- Start job description -----------------------
#SBATCH --partition=standard
#SBATCH --job-name=my_job
#SBATCH --ntasks=1
#SBATCH --mem-per-cpu=1000
#SBATCH --time=12:00:00
#SBATCH --mail-type=ALL
#SBATCH --mail-user=user@example.com
##------------------------ End job description ------------------------

module purge && module load <app>

srun <app> --app-param app_args

Importante

Las directivas deben ser lo primero que aparezca en el fichero antes de cualquier línea que se pueda ejecutar.

Aunque SLURM proporciona multitud de directivas para configurar un trabajo, existe un conjunto reducido de directivas comunes:

Opción Abreviado Descripción
--job-name=name -J name Nombre del trabajo. Es meramente informativo y para facilitar la identificación.
--partition=name -p name Partición a utilizar.
--nodes=# -N # Número de nodos a utilizar.
--ntasks=# -n # Número de tareas a ejecutar (paralelismo distribuido)
--ntasks-per-node=#   Número de tareas asignadas a cada nodo físico.
--time=[[DD-]HH:]MM:SS -t [[DD-]HH:]MM:SS Duración máxima de ejecución del trabajo.
--mem-per-cpu=#   Memoria RAM requerida por CPU (MB).
--mem=#   Memoria RAM requerida por nodo (MB).
--output=out-%j.log -o out-%j.log Fichero para almacenar la salida estandar del job
--error=err-%j.log -e err-%j.log Fichero para almacenar la salida de errores del job.
--mail-user=email   Dirección de correo.
--mail-type=ALL   Enviar correos electrónicos al usuario en todos los eventos de trabajo.
--chdir=[dir_name]   Directorio de trabajo.

Nota

Aunque se puede utilizar la versión abreviada, se recomienda utilizar la versión larga por claridad.

Por ejemplo, es muy fácil confundir las opciones -N (número de nodos) y -n (número de tareas) en las cabeceras de un job.

Nota

Se puede obtener información detallada de todas las directivas disponibles consultando la documentación de sbatch o ejecutando man sbatch en uno de los nodos interactivos.

3.3. Límites de ejecución

Para facilitar una utilización eficiente de los recursos se han establecido una serie de límites. Estos límites permiten cierta flexibilidad para acomodar la ejecución de múltiples trabajos.

El principal límite es el trabajo máximo que se puede enviar al sistema. En el caso de la partición standard se pueden solicitar 600 cores o lo que es equivalente 2400 GB de memoria RAM durante 72 horas. Sin embargo, es posible incrementar la duración de un trabajo si se solicitan menos cores (Ej.: se puede reservar 300 cores y 1200 GB de RAM hasta 144 horas) aunque nunca se puede superar las 160 horas.

Partition Max CPUs = Mem RAM / duración Duración máxima
standard 600 cores = 2400 GB / 72 horas 160 horas
debug 40 cores = 160 GB /15 minutos 1 hora

Nota

Los límites establecen una cota máxima siendo válida cualquier combinación que los cumpla. De hecho lo recomendable es ajustar al máximo los recursos solicitados (con cierto margen de seguridad) para facilitar la planificación y que el trabajo pueda entrar a ejecutar.

Importante

Le aconsejamos hacer un uso correcto de los recursos, solicitando unicamente los necesarios para la ejecución de cada trabajo.

3.4. Redirección de salidas

Las aplicaciones suelen escribir datos o resultados por la consola. Al procesarme mediante un sistema de proceso por lotes, estas salidas se perderían al no existir una consola en el momento de ejecución. Para evitarlo SLURM redirige esas salidas a ficheros en disco dónde se pueden consultar.

Por defecto, SLURM almacena ambas salidas en el fichero slurm-<id_job>.out. Este fichero se crea automáticamente al iniciar la ejecución en el directorio del trabajo.

Es posible redefinir el nombre y ubicación mediante las directivas --output=<outfile> y --error=<errfile>, pudiendo incluso separarlas en dos ficheros. Dentro del nombre existen algunos tokens que se reemplazarán automáticamente por los datos del trabajo:

\
Evita el proceso de los reemplazos
%%
Genera un único «%».
%A
Identificador del trabajo (si se usan arrays)
%a
Índice del trabajo (si se usan arrays).
%J
Identificador de trabajo y paso (equivale a %j.%s)
%j
Identificador del trabajo
%N
Nombre del nodo. Creará un fichero diferente para cada nodo que participe en la ejecución.
%n
Identificador del nodo. Creará un fichero diferente para cada nodo que participe en la ejecución.
%s
Identificador del paso (número de srun ejecutados)
%t
Identificador de la tarea (rank) dentro del trabajo. Creará un fichero diferente por cada tarea.
%u
Usuario
%x
Nombre del trabajo.

Importante

El directorio donde se almacenan las redirecciones debe existir y se debe poder crear los ficheros en su interior. Si no es así el trabajo abortará sin ningún tipo de indicación.

Por ejemplo:

  • Redirigir la salida y el error a dos ficheros diferentes:

    --output=out-%j.log
    --output=err-%j.log
    
  • Redirigir la salida y el error de cada paso y tarea a su propio fichero:

    --output=out-%J.%t.log
    --output=err-%J.%t.log
    

3.5. Notificaciones

Se puede configurar el envío automático de un correo cuando se produzcan modificaciones en el estado de un trabajo.

Para ello hay que añadir las opciones --mail-user indicando el correo al que se deben enviar las notificaciones y --mail-type con los eventos de interés separados por comas:

  • BEGIN
  • END
  • FAIL
  • REQUEUE
  • STAGE_OUT (el trabajo ha finalizado incluyendo las labores de limpieza.)

Se puede indicar ALL como una abreviatura de todos los eventos anteriores y NONE para ninguno

Adicionalmente se pueden solicitar avisos cuando se alcance cierto porcentaje el límite de tiempo especificado:

Evento Porcentaje
TIME_LIMIT 100%
TIME_LIMIT_90 90%
TIME_LIMIT_80 80%
TIME_LIMIT_50 50%

3.6. Configuraciones específicas

Gracias a la flexibilidad en la configuración, Magerit permite la ejecución de trabajos con multitud de esquemas de trabajos que dependen de la capacidad del software y de lo que se desee hacer.

Nota

En estos ejemplos sólo se indican las directivas mínimas de interés, aunque se pueden añadir y combinar con cualquier otra directiva.

3.6.1. Trabajos paralelos con MPI

MPI (Message Passing Interface) es un mecanismo para la programación paralela por paso de mensajes que no necesita que todos los procesos ejecuten en el mismo nodo. La cantidad de estos procesos se maneja con la directiva --ntasks.

1
2
3
4
5
6
7
8
#!/bin/bash
#----------------------- Start job description -----------------------
#SBATCH --ntasks=#
##------------------------ End job description ------------------------

module purge && module load <app>

srun <app> --app-param app_args

3.6.2. Trabajos secuenciales

Los trabajos secuenciales no utilizan paralelismo, aunque suelen soportar OpenMP ya sea directamente en la aplicación o mediante el uso de alguna librería que lo haga.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash
#----------------------- Start job description -----------------------
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=#
##------------------------ End job description ------------------------

module purge && module load <app>
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK

srun <app> --app-param app_args

En algunos casos, la ejecución puede mejorar si se reservan más recursos (Ej.: con OpenMP habilitado).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash
#----------------------- Start job description -----------------------
#SBATCH --ntasks=1
#SBATCH --cpus-per-task=40
##------------------------ End job description ------------------------

module purge && module load <app>
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK

srun <app> --app-param app_args

Importante

En este esquema de ejecución el número de tareas debe ser 1. Al ser trabajos secuenciales sólo se utiliza la primera tarea desperdiciándose el resto de los recursos.

3.6.3. Trabajos híbridos

Los trabajos híbridos MPI+OpenMP consisten en ejecutar varios procesos MPI (definidos por --ntasks) y, cada uno de ellos, desplegará varios hilos OpenMP (definidos por –cpus-per-task). A efectos contable, equivale a reservar ntasks x cpus-per-task CPUs.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash
#----------------------- Start job description -----------------------
#SBATCH --ntasks=#
#SBATCH --cpus_per_task=#
##------------------------ End job description ------------------------

module purge && module load <app>
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK

srun <app> --app-param app_args

Nota

Es necesario que la aplicación implemente estos dos paralelismos para obtener el máximo rendimiento.

3.6.4. Múltiples programas

Aunque lo más común es ejecutar el mismo programa en todas las tareas, en ocasiones es necesario ejecutar diferentes operaciones (MPMD - Multiple Program Multiple Data). Un posible caso es cuando se quiere aglutinar en una simple ejecución diferentes procesos «rápidos» para ejecutarlos en un único job.

Para simplificar estas ejecuciones existe la opción --multi-prog de SLURM. Para ello hay que definir dos ficheros:

1
2
3
4
5
6
7
8
9
#!/bin/bash
##----------------------- Start job description -----------------------
#SBATCH --ntasks=#
##------------------------ End job description ------------------------

module purge && module load <app>
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK

srun --multi-prog job.list

La línea de srun simplemente indica el fichero donde se encuentran las ejecuciones que se desean hacer. Este fichero tiene dos campos:

Rank:

Identificador de la tarea a ejecutar (número de rank de MPI). Empieza en cero.

Es posible indicar conjuntos (0,2,5), rangos (0-3) o cualquier combinación (0,2-3,5).

Ejecutable y argumentos:

Programa que se desea ejecutar seguido de los argumentos que precise.

Se puede utilizar la expresión %t, que será sustituida por el número de tarea, y %o que será sustituido por el desplazamiento (el rank 1-5 tendrán desplazamientos 0-4).

1
2
3
4-6       cmd1
1,7       cmd2 task:%t
0,2-3     cmd3 offset:%o

Importante

El número de tareas (--ntasks) debe ser compatible con las indicadas en job.list.