Slurm
O Slurm, é um agendador de jobs gratuito e de código aberto para kernels Linux, usado por muitos supercomputadores e clusters de computadores do mundo. Ele fornece três funções principais:
- Alocar acesso exclusivo e/ou não exclusivo aos recursos (nós de computador) aos usuários por um determinado período de tempo para que eles possam executar o trabalho.
- Fornecer uma estrutura para iniciar, executar e monitorar o trabalho, normalmente um trabalho paralelo, como a Interface de Passagem de Mensagens (MPI) em um conjunto de nós alocados.
- E arbitrando a disputa por recursos gerenciando uma fila de trabalhos pendentes.
Slurm é o gerenciador de carga de trabalho em cerca de 60% dos supercomputadores TOP500.[2]
O Slurm organiza o uso dos computadores do cluster assim:
- Ele tem máquinas (nós) que fazem as contas.
- Essas máquinas são divididas em filas (partições), cada fila com suas regras (quanto tempo pode rodar, quem pode usar, etc.).
- Quando você pede para rodar um cálculo (job), o Slurm reserva para você um pedaço dessas máquinas por um tempo.
- Dentro desse job, você pode rodar várias tarefas (job steps), que podem usar todas as máquinas de uma vez ou só uma parte delas.
O usuário envia o job ou tarefa que deseja executar no cluster, especificando o programa e quantidade de recursos como cpu, memória.
Entre os comandos usados, podemos usar os comandos de visualização de informação:
sinfo: Um comando muito utilizado é o sinfo, com ele podemos ver o estado dos nós e partições disponíveis.
sinfo -s
PARTITION AVAIL TIMELIMIT NODES(A/I/O/T) NODELIST
debug* up infinite 1/0/1/2 idpx[01-02]
serial up 2:00:00 1/0/1/2 idpx[01-02]squeue: visualização de informações sobre o status dos jobs e escalonamento.
squeue
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
27 debug teste bruno PD 0:00 1 (Resources)
26 debug teste bruno R 0:07 1 idpx02Outras opções para usar com o squeue: -s -u (user), -A (account), -p (partition)
Podendo monitorar os jobs enviados com squeue, que podemos usar para saber em que estado ele está, se já começou a rodar, se ainda está aguardando na fila.
$ squeue
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
15 debug teste bruno R 0:04 1 idpx01Assim temos na saída as informações:
JOBID : número do job.
PARTITION : fila usada.
NAME : nome do job.
USER : quem submeteu.
ST : estado (R = running, PD = pending, F = finished).
TIME : tempo de execução.
NODES : número de nós alocados.
NODELIST : onde está rodando (ou motivo de espera).
srun: usado para fazer a alocação de recursos e distribuição de tarefas.
$ srun -p serial --nodes=1 sleep 6$ squeue -u $USER
JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
30 serial sleep bruno R 0:09 1 idpx02$ scontrol --details show job 30
JobId=30 JobName=sleep
UserId=bruno(221203245) GroupId=domain users(221200513) MCS_label=N/A
Priority=1 Nice=0 Account=(null) QOS=normal
JobState=RUNNING Reason=None Dependency=(null)
Requeue=1 Restarts=0 BatchFlag=0 Reboot=0 ExitCode=0:0
DerivedExitCode=0:0scontrol: ferramentta para visualizar e/ou modificar o estado de um job.
$ scontrol show job 32
JobId=32 JobName=teste
UserId=bruno(1001) GroupId=users(100)
Priority=4294901746 Nice=0 Account=default
JobState=RUNNING
RunTime=00:02:13 TimeLimit=01:00:00
NumNodes=1 NumCPUs=4
NodeList=node02Para verificar informações dos nodes com scontrol.
$ scontrol show node
NodeName=idpx01 CoresPerSocket=6
CPUAlloc=0 CPUEfctv=24 CPUTot=24 CPULoad=0.00
AvailableFeatures=(null)
ActiveFeatures=(null)
Gres=(null)
NodeAddr=idpx01 NodeHostName=idpx01
RealMemory=48254 AllocMem=0 FreeMem=N/A Sockets=2 Boards=1
State=DOWN+NOT_RESPONDING ThreadsPerCore=2 TmpDisk=0 Weight=1 Owner=N/A MCS_label=N/A
Partitions=debug,serial
BootTime=None SlurmdStartTime=None
LastBusyTime=2026-03-10T21:47:17 ResumeAfterTime=None
CfgTRES=cpu=24,mem=48254M,billing=24Para verificar informações de filas (partition) com scontrol.
scontrol show partition
PartitionName=debug
AllowGroups=ALL AllowAccounts=ALL AllowQos=ALL
AllocNodes=ALL Default=YES QoS=N/A
DefaultTime=NONE DisableRootJobs=NO ExclusiveUser=NO GraceTime=0 Hidden=NO
MaxNodes=UNLIMITED MaxTime=UNLIMITED MinNodes=0 LLN=NO MaxCPUsPerNode=UNLIMITED MaxCPUsPerSocket=UNLIMITED
NodeSets=ALL
Nodes=idpx[01-02]
PriorityJobFactor=1 PriorityTier=1 RootOnly=NO ReqResv=NO OverSubscribe=NO
OverTimeLimit=NONE PreemptMode=OFF
State=UP TotalCPUs=48 TotalNodes=2 SelectTypeParameters=NONE
JobDefaults=(null)
DefMemPerNode=UNLIMITED MaxMemPerNode=UNLIMITED
TRES=cpu=48,mem=96508M,node=2,billing=48Para submissão de jobs usamos o comando sbatch, que envia um script em lote para o Slurm. O script em lote pode ser fornecido ao sbatch por meio de um nome de arquivo na linha de comando ou, se nenhum nome de arquivo for especificado, o sbatch lerá um script da entrada padrão. Vamos ao primeiro exemplo, crie o script abaixo com seu editor de texto preferido:
#!/bin/bash
#SBATCH --job-name=teste
#SBATCH --output=saida_%j.txt
#SBATCH --time=00:10:00
#SBATCH --nodes=1
#SBATCH --ntasks=1
echo "Rodando no nó $(hostname)"
sleep 30Agora basta submeter o job:
sbatch script.shÉ importante sempre usar –output para logs e pedir corretamente os recursos necessários para seu job, assim o slurm consegue gerenciar melhor a fila de execuções, alguns dos recursos:
Tempo: #SBATCH –time=02:00:00
Memória: #SBATCH –mem=4G
CPUs: #SBATCH –cpus-per-task=4
Nós: #SBATCH –nodes=2
GPU: #SBATCH –gres=gpu:1
Partição: #SBATCH –partition=long
Outro exemplo usando variáveis de ambiente do slurm. Para esse exemplo vamos usar um código em C, que imprime:
- Thread do OpenMP
- Número total de threads
- Algumas variáveis do Slurm
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main() {
int thread_id, nthreads;
#pragma omp parallel private(thread_id)
{
thread_id = omp_get_thread_num();
nthreads = omp_get_num_threads();
printf("Hello from thread %d of %d\n", thread_id, nthreads);
if (thread_id == 0) {
printf("\n--- Informações do Slurm ---\n");
printf("Job ID: %s\n", getenv("SLURM_JOB_ID"));
printf("Node: %s\n", getenv("SLURMD_NODENAME"));
printf("CPUs por tarefa: %s\n", getenv("SLURM_CPUS_PER_TASK"));
printf("Total de tasks: %s\n", getenv("SLURM_NTASKS"));
printf("-----------------------------\n\n");
}
}
return 0;
}Para compilação:
$ gcc -fopenmp hello_openmp.c -o hello_openmpNo script de submissão, podemos usar as variáveis do slurm, para melhor documentar ou logar as saídas de execução.
#!/bin/bash
#SBATCH --job-name=openmp_test
#SBATCH --output=saida_%j.out
#SBATCH --cpus-per-task=4
#SBATCH --time=00:02:00
echo "================================"
echo "Informações do Job"
echo "================================"
echo "Job ID: $SLURM_JOB_ID"
echo "Usuário: $SLURM_JOB_USER"
echo "Node: $SLURMD_NODENAME"
echo "CPUs por tarefa: $SLURM_CPUS_PER_TASK"
echo "Diretório de submissão: $SLURM_SUBMIT_DIR"
echo ""
echo "Definindo número de threads OpenMP..."
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
echo "OMP_NUM_THREADS=$OMP_NUM_THREADS"
echo ""
echo "Executando programa..."
./hello_openmpAlgumas variáveis importantes que o Slurm injeta automaticamente:
Variável Significado
SLURM_JOB_ID: ID do job
SLURM_JOB_USER: usuário que submeteu
SLURM_CPUS_PER_TASK: CPUs reservadas
SLURM_NTASKS: número de tasks
SLURMD_NODENAME: nó onde está rodando
SLURM_SUBMIT_DIR: diretório de onde o job foi submetido
Caso o Slurm esteja instalado com a opção de accounting, podemos consultar jobs que já terminaram ou ainda estão ativos, com informações detalhadas de uso de recursos com o comando sacct.
$ sacct
JobID JobName Partition Account AllocCPUS State ExitCode
----- ------ ---------- -------- ---------- ---------- --------
15 teste debug 2 COMPLETED 0:0
15.batch batch 2 COMPLETED 0:0 Podemos personalizar a saída do comando sacct usando a opção –format, seguida de uma lista das informações que desejamos exibir.
sacct -j 32 --format=JobID,JobName,State,Elapsed,NCPUS,MaxRSS,ExitCode
JobID JobName State Elapsed NCPUS MaxRSS ExitCode
------------ ---------- ---------- ---------- ---------- ---------- --------
32 cat COMPLETED 00:00:00 6 0:0
32.0 cat COMPLETED 00:00:00 6 0:0O comando scancel, permite cancelar trabalhos, muito útil se você percebe que configurou errado os recursos ou se não precisa mais daquele job.
$ scancel 12345