La ejecución de trabajos se realiza mediante la herramienta SLURM, un workload manager y job scheduler que gestiona la ejecución de trabajos y recursos computacionales según el orden y prioridad. Gracias a SLURM, es posible una convivencia ordenada y justa entre múltiples usuarios sin interrumpirse entre ellos.
Las particiones son un conjunto de recursos agrupados para un determinado propósito. En el caso del Patagón, existen cuatro particiones
PARTICIÓN EN MANTENCIÓN
Esta partición es ideal para trabajos GPU de inteligencia artificial. Puede consultar mas información con el comando scontrol show partition A100
Partición por defecto del Patagón y es para todo tipo de trabajos GPU. Puede consultar mas información con el comando scontrol show partition L40
Esta partición es para trabajos GPU livianos. Puede consultar mas información con el comando scontrol show partition A4000
Para trabajos de CPU secuenciales o paralelos. Puede consultar con el comando scontrol show partition cpu
.
Ejecutaremos un job SLURM con el comando nvidia-smi
, el cual lista las GPUs disponibles para utilizar.
➜ ~ srun -p L40 nvidia-smi -L
No devices found.
La respuesta "No devices found.
es el resultado esperado ya que SLURM asume 0 GPUs por defecto. Para solicitar GPUs, es necesario adicionar el parámetro --gpus=<num>
, donde <num>
es la cantidad de GPUs a solicitar de la partición. Por ejemplo, si queremos ejecutar nvidia-smi -L
con una GPU, seria así:
➜ ~ srun -p rtx --gpus=1 nvidia-smi -L
GPU 0: NVIDIA L40 (UUID: GPU-2ee80d8a-f11f-1db1-6b83-d17d0b514179)
El valor de <num>
define la cantidad de GPUs a reservar.
Otro ejemplo, ahora pidiendo 2 GPUs
➜ ~ srun -p L40 --gpus=2 nvidia-smi -L
GPU 0: NVIDIA L40 (UUID: GPU-2bf13726-6ccf-5c71-282b-7537a29637be)
GPU 1: NVIDIA L40 (UUID: GPU-2ee80d8a-f11f-1db1-6b83-d17d0b514179)
Si se solicitan mas GPUs que las permitidas o libres, SLURM dejara encolado el trabajo hasta que los recursos estén disponibles. Para saber los recursos en uso, es posible usar el comando pat
que es propio del Patagón. Por ejemplo:
➜ ~ pat resources
+---------------------------------------------------------+
| Patagón Resources (in use) v1.12-250716 |
+------------+--------------+--------------+--------------+
| Partition | CPU cores | RAM | GPUs |
+------------+--------------+--------------+--------------+
| A4000 | 16/32 | 268GB/704GB | 2/3 |
| cpu | 21/64 | 268GB/704GB | n/a |
| L40* | 8/32 | 268GB/704GB | 1/3 |
+------------+--------------+--------------+--------------+
Para mas información, pat --help
.
En Patagón, las dependencias de librerías o software se satisface mediante contenedores. Es decir, al ejecutar un trabajo por SLURM, el usuario indica el contenedor que necesita para ejecutar el trabajo. Este contenedor se descarga automáticamente por el plugin pyxis
para SLURM y la herramienta enroot
para ejecutar contenedores. Así, el contenedor se transforma en el nuevo entorno de trabajo del usuario, el cual puede ser modificado a gusto sin afectar a los otros usuarios ni a la configuración nativa del Patagón. Al finalizar la tarea, el contenedor se desmonta automáticamente del nodo de computo por defecto.
Para poder entender mejor la función de los contenedores, ejecutemos nvcc --version
para consultar la versión del compilador de CUDA nvcc
.
➜ ~ srun -p L40 nvcc --version
slurmstepd: error: execve(): nvcc: No such file or directory
srun: error: nodeGPU02: task 0: Exited with exit code 2
Hemos tenido un error como resultado. Esto ocurre porque el nodo de cómputo carece de alguna versión particular de CUDA. Para lograr hacer funcionar este ejemplo, necesitamos indicar un contenedor que incluya CUDA al momento de ejecutar nuestra tarea. Nvidia GPU Cloud (NGC) ofrece diversos contenedores para utilizar, incluyendo el contenedor de CUDA. En este caso, hemos escogido la versión 12.9 de CUDA y la variante devel
que incluye las herramientas de desarrollo. El comando para descargar el contenedor es (puede tardar algunos minutos):
➜ ~ srun -p L40 --container-name=cuda-12.9 --container-image='nvcr.io/nvidia/cuda:12.9.1-devel-ubuntu24.04' nvcc --version
pyxis: importing docker image: nvcr.io/nvidia/cuda:12.9.1-devel-ubuntu24.04
pyxis: imported docker image: nvcr.io/nvidia/cuda:12.9.1-devel-ubuntu24.04
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2025 NVIDIA Corporation
Built on Tue_May_27_02:21:03_PDT_2025
Cuda compilation tools, release 12.9, V12.9.86
Build cuda_12.9.r12.9/compiler.36037853_0
Para lograr que pyxis/enroot puedan descargar y utilizar automáticamente contenedores de una URL especificada por el usuario, debe configurar sus credenciales.
El parámetro --container-image=<URL>
indica la URL del contenedor, mientras que el parámetro --container-name=<nombre>
es un alias para futuros jobs (una vez descargado, se reutiliza).
➜ ~ srun -p L40 --container-name=cuda-12.9 -nvcc --version
pyxis: importing docker image: nvcr.io/nvidia/cuda:12.9.1-devel-ubuntu24.04
pyxis: imported docker image: nvcr.io/nvidia/cuda:12.9.1-devel-ubuntu24.04
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2025 NVIDIA Corporation
Built on Tue_May_27_02:21:03_PDT_2025
Cuda compilation tools, release 12.9, V12.9.86
Build cuda_12.9.r12.9/compiler.36037853_0
Nota (Julio 2025): Debido a cambios recientes en pyxis
, para mantener la misma ubicación dentro del job es necesario incluir --container-workdir=${PWD}
como opcion a srun
.
Por ejemplo, si el usuario es user
y esta actualmente ubicado en /home/user/
, entonces:
➜ ~ pwd
/home/user
➜ ~ srun --container-name=cuda-12.9 pwd
/
➜ ~ srun --container-workdir=${PWD} --container-name=cuda-12.9 pwd
/home/user
srun
(tiempo-real, anclado a la sesión)El comando srun
permite a los usuarios ejecutar trabajos para verlos en ejecución de forma directa e interactiva en el terminal. Este modo es síncrono con la sesión, es decir, el terminal queda anclado a la ejecución y progreso del trabajo, y si uno termina su sesión (i.e., se desconecta del Patagón), entonces el trabajo se cancela (a menos que este usando screen
o algo similar). El comando srun
sigue la estructura
srun --container-workdir=${PWD} <contenedor> <recursos> <tarea>
srun
Usaremos un ejemplo de nuestro repositorio Patagón samples (https://github.com/patagon-uach/patagon-samples). En particular patagon-samples/01-custom-programs/03-GPU-single/
el cual multiplica dos matrices. Primero compilaremos.
➜ srun --container-workdir=${PWD} --container-name=cuda-12.9 make
nvcc -O3 -arch=sm_80 -lnvidia-ml -Xcompiler -fopenmp main.cu -o prog
➜
Y luego ejecutaremos con una GPU (ese ejemplo fue programado para una GPU solamente)
➜ 03-GPU-single git:(main) ✗ srun -p L40 --container-workdir=${PWD} --container-name=cuda-12.9 --gpus=1 ./prog 0 $((1024*30)) 1
GPU MATMUL
size: 30720 x 30720
mode 1
Exploring GPUs
Driver version: 550.127.08
NUM GPUS = 1
Listing devices:
GPU0 NVIDIA L40, index=0, UUID=GPU-2bf13726-6ccf-5c71-282b-7537a29637be -> util = 0%
Choosing GPU 0
initializing A and B.......done
matmul shared mem..........done: time: 9.564180 secs
copying result to host.....done
verifying result...........done
sbatch
(desacoplado de la sesión)El comando sbatch
permite ejecutar tareas por lotes sin la necesidad de mantener la sesión abierta, es decir el usuario puede desconectarse luego de haber lanzado su trabajo con sbatch
. Para utilizar sbatch
es necesario escribir un script, típicamente con extensión *.slurm
(sirve para mantener orden), en el cual se indican los recursos a solicitar, el contenedor, y la tarea en particular. Una tarea sbatch
puede contener múltiples llamadas a srun
, y aun seguirá siendo considerada como una sola tarea. Esto ultimo es de gran utilidad cuando necesitamos construir un gran trabajo compuesto de tareas menores. Por ejemplo, una tarea que conste de pre-procesamiento, procesamiento y post-procesamiento podría ser construida con tres llamadas a srun
dentro de un script *.slurm
.
sbatch
Usemos el mismo ejemplo de patagon samples de github (https://github.com/patagon-uach/patagon-samples) y pondremos la compilación y ejecución en el script para sbatch
. El siguiente script contiene el detalle de la ejecución para sbatch
(ya existe en el ejemplo del repositorio)
#!/bin/bash
# IMPORTANT PARAMS
#SBATCH -p L40 # Submit to which partition
#SBATCH --gpus=1 # GPU resources, format TYPE:device:quantity
# OTHER PARAMS
#SBATCH -J TUT03-single-GPU # Name the job
#SBATCH -o TUT03-single-GPU-%j.out # Write the standard output to file named 'jMPItest-<job_number>.out'
#SBATCH -e TUT03-single-GPU-%j.err # Write the standard error to file named 'jMPItest-<job_number>.err'
# COMMANDS ON THE COMPUTE NODE
pwd # prints current working directory
date # prints the date and time
# compile the GPU program
srun --container-workdir=${PWD} --container-name=cuda-12.9 make
# run the GPU program
srun --container-workdir=${PWD} --container-name=cuda-12.9 ./prog 0 $((1024*40)) 1
Ejecutamos el job con sbatch
:
➜ 03-GPU-single git:(main) sbatch launch.slurm
Submitted batch job 68448
Revisando rápidamente la cola de trabajo con el comando squeue
, podemos identificar el job por su ID:
➜ 03-GPU-single git:(main) squeue
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
68402 A4000 napgan_L simonesc R 8:36:33 1 nodeGPU02
68401 A4000 napgan_L simonesc R 11:54:42 1 nodeGPU02
68448 L40 TUT03-si cnavarro R 0:05 1 nodeGPU02 <------- JOB
68398 L40 Qwen-Eva cris R 12:39:00 1 nodeGPU02
68416 cpu hy_nnt11 hgarces R 2:44:17 1 nodeGPU02
68403 cpu bash naye R 4:12:30 1 nodeGPU02
Un job por sbatch
no genera output en la pantalla, sino que en sus archivos de error (err
) y salida (out
).
➜ 03-GPU-single git:(main) ls
launch.slurm main.cu Makefile prog srun.txt TUT03-single-GPU-68448.err TUT03-single-GPU-68448.out
Revisando cada uno podemos ver que no hay errores y que el output es el mismo de cuando se ejecuto con srun
:
➜ 03-GPU-single git:(main) cat TUT03-single-GPU-68448.err
➜ 03-GPU-single git:(main) cat TUT03-single-GPU-68448.out
/home/cnavarro/patagon-samples/01-custom-programs/03-GPU-single
Thu Jul 17 11:39:38 PM -04 2025
nvcc -O3 -arch=sm_80 -lnvidia-ml -Xcompiler -fopenmp main.cu -o prog
GPU MATMUL
size: 40960 x 40960
mode 1
Exploring GPUs
Driver version: 550.127.08
NUM GPUS = 1
Listing devices:
GPU0 NVIDIA L40, index=0, UUID=GPU-2bf13726-6ccf-5c71-282b-7537a29637be -> util = 0%
Choosing GPU 0
initializing A and B.......done
➜