====== ARREGLOS DE TRABAJOS ====== Los arreglos de trabajos permiten enviar muchas tareas que difieren en un solo parámetro (por ejemplo el fichero de entrada, el directorio que contiene los datos, entre otros), de forma más eficiente que enviando las tareas individualmente. Se conocen también como //array job//, //job array// y //array task//. **Especificación** Existen diferentes formas de especificar los arreglos: #SBATCH --array=0-31 # - intervalo #SBATCH --array=1,3,5,7 # , valores individuales #SBATCH --array=1-7:2 # : salto El número de tareas ejecutándose al mismo tiempo se puede especificar con el signo %. #SBATCH --array=1-31%5 # 5 tareas ejecutándose del arreglo 1-31. Es importante especificar el número de tareas ejecutándose a valores no más de 5 o 6, para no ocupar todos los nodos con un solo //array job//. **JOB ID y Variables de ambiente** Además de la variable //SLURM_JOB_ID// que se crea para cada trabajo, con los arreglos se crean otras variables de ambiente: SLURM_ARRAY_JOB_ID se dará al primer job ID del arreglo. SLURM_ARRAY_TASK_ID se dará al valor del índice del job array. SLURM_ARRAY_TASK_COUNT se dará al número de las tareas en el arreglo. SLURM_ARRAY_TASK_MAX se dará al mayor valor del valor del índice del arreglo. SLURM_ARRAY_TASK_MIN se dará al menor valor del valor del índice del arreglo. Por ejemplo, si se envía un --//array1-3// y Slurm responde: Submitted batch job 36 entonces se tiene: SLURM_JOB_ID=36 SLURM_ARRAY_JOB_ID=36 SLURM_ARRAY_TASK_ID=1 SLURM_ARRAY_TASK_COUNT=3 SLURM_ARRAY_TASK_MAX=3 SLURM_ARRAY_TASK_MIN=1 SLURM_JOB_ID=37 SLURM_ARRAY_JOB_ID=36 SLURM_ARRAY_TASK_ID=2 SLURM_ARRAY_TASK_COUNT=3 SLURM_ARRAY_TASK_MAX=3 SLURM_ARRAY_TASK_MIN=1 SLURM_JOB_ID=38 SLURM_ARRAY_JOB_ID=36 SLURM_ARRAY_TASK_ID=3 SLURM_ARRAY_TASK_COUNT=3 SLURM_ARRAY_TASK_MAX=3 SLURM_ARRAY_TASK_MIN=1 Todas estas variables se pueden utilizar en los scripts de envío, pero las más usadas son //SLURM_JOB_ID// y //SLURM_ARRAY_JOB_ID//. **Nombres de ficheros** Para especificar los nombres de ficheros de //stdin//, //stdout// y //sterr//, se sustituyen %A por //SLURM_ARRAY_JOB_ID// y %a por //SLURM_ARRAY_TASK_ID//. Por ejemplo: #SBATCH --output=array_%A_%a.out #SBATCH --error=array_%A_%a.err **Especificar correo** Por defecto Slurm envía correos cuando el trabajo termina, comienza o falla (END, BEGIN, FAIL). En el caso de los arreglos de trabajo, el correo se refiere al //job array// y no a las tareas. En caso que se desee el envío del correo por las tareas añada: //ARRAY_TASKS//. Se debe tener cuidado al usar //ARRAY_TASKS// por el número de correos que pueda generar. **Ejemplos** **Caso 1. 1000 trabajos similares con los mismos recursos, pero con ficheros de entrada diferentes** Ficheros de entrada: fichero-1, fichero-2, ..., fichero-1000 #SBATCH --array=1-1000%5 # 1000 trabajos ejecutándose 5 cada vez #SBATCH --output=array_%A_%a.out #SBATCH --error=array_%A_%a.err ./programa < fichero-$SLURM_ARRAY_TASK_ID **Caso 2. El caso anterior pero con ficheros en diferentes directorios** Directorios: directorio1/, directorio2/, ... con fichero-1, fichero-2, ... en cada directorio respectivamente. Crear el fichero //lista_directorios.txt// con los nombres de los directorios en columna. Es importante notar que los nombres de los directorios pueden no tener una raíz única, no ser iguales e incluso no tener números consecutivos, sino números en cualquier orden. #SBATCH --array=1-1000%5 # 1000 jobs ejecutándose 5 cada vez #SBATCH --output=array_%A_%a.out #SBATCH --error=array_%A_%a.err # Define la variable DIR usando sed y la lista_directorios.txt DIR=$(sed -n "${SLURM_ARRAY_TASK_ID}p" lista_directorios.txt) # Cambia al directorio DIR cd $DIR # Ejecuta el programa ./programa < fichero-$SLURM_ARRAY_TASK_ID {{ :wiki:caso2_array_gaussian.rar |Descargar ejemplo}}. Otra forma más sencilla de hacer este caso es de la siguiente forma: - Crear un directorio con fichero-1, fichero-2, ... - Utilizar las siguientes directivas en el script de envío: #SBATCH --array=1-1000%5 # 1000 jobs ejecutándose 5 cada vez #SBATCH --output=array_%A_%a.out # STDOUT #SBATCH --error=array_%A_%a.err # STDERR # Cambia al directorio del id de la tarea cd $SLURM_ARRAY_TASK_ID # Ejecuta el programa ./programa < fichero-$SLURM_ARRAY_TASK_ID En esta última forma se utiliza la variable //$SLURM_ARRAY_TASK_ID//, que almacena el id de la tarea del arreglo. **Caso 3. El caso 2 pero con 5000 trabajos en vez de 1000** Es poco eficiente ejecutar 5000 trabajos en un nodo, por lo que es mejor hacer ciclos con 1000 en un nodo. De esta forma, se tendrán 5 trabajos haciendo cada uno ciclos de 1000. Directorios: directorio1/, directorio2/, ... con fichero-1, fichero-2, ... Crear el fichero //lista_directorios.txt// con los nombres de los directorios en columna. En el siguiente script se combina el //array task// con ciclos de //bash// para procesar varias ejecuciones cortas. #SBATCH --array=1-5 #SBATCH --output=array_%A_%a.out #SBATCH --error=array_%A_%a.err # Número de ejecuciones que cada tarea de Slurm debe hacer NUMLINES=1000 # Calcula valores iniciales y finales de esta tarea basados en el task id y el número de ejecuciones STOP=$((SLURM_ARRAY_TASK_ID*NUMLINES)) START="$(($STOP - $(($NUMLINES - 1))))" # Ejecuta un ciclo de bash para esta tarea for (( N = $START; N <= $STOP; N++ )) do DIR=$(sed -n "${SLURM_ARRAY_TASK_ID}p" lista_directorios.txt) cd $DIR endo # Ejecuta el programa ./programa < fichero-$SLURM_ARRAY_TASK_ID **Caso 4. Diferentes opciones para un programa** Es posible pasar diferentes opciones a un programa usando el //array task id//. Se escribe un fichero //file.txt// que contenga en cada línea los argumentos //ARG1//, //ARG2//, ... El siguiente es un ejemplo de programa Python al que se le pasan diferentes opciones: #SBATCH --array=0-4 #SBATCH --output=array_%A_%a.out #SBATCH --error=array_%A_%a.err case $SLURM_ARRAY_TASK_ID in 0) ARGS="-i foo.txt -o foo.out" ;; 1) ARGS="-i bar.txt -o bar.out" ;; 2) ARGS="-i ich.txt -o ich.txt" ;; 3) ARGS="-i pin.txt -o pin.txt" ;; 4) ARGS="-i lsin.txt -o lsin.txt" ;; esac python program.py $ARGS > output-$SLURM_ARRAY_TASK_ID.txt {{ :wiki:caso4ejemplo.rar |Descargar ejemplo}}. **Notas importantes** Para que los programas escritos en Python y R puedan leer el //array task id// es necesario cargar los módulos correspondientes. Python: import sys jobid = sys.getenv(´SLURM_ARRAY_TASK_ID´) R: task_id <- Sys.getenv(¨SLURM_ARRAY_TASK_ID¨)