Job Array

Job Array é uma funcionalidade do SLURM que permite submeter múltiplos jobs similares com um único script. É ideal para High Throughput Computing (HTC).

Conceito

Um job array é um conjunto de jobs independentes, cada um com seu próprio índice. Todos compartilham o mesmo script de submissão, mas podem processar dados diferentes baseados no índice.

Analogia: Você contrata uma empresa de confecções (o Cluster HPC) e entrega um único molde (o script de job) e uma lista de parâmetros (os nomes das cores ou um intervalo de números, como 0 a 10). A empresa (Slurm) analisa o molde e disponibiliza 8 costureiras/os (CPUs) para trabalhar (processar) simultaneamente, cada costureira/o pegando um parâmetro (cor) diferente da lista usando o $SLURM_ARRAY_TASK_ID.

Quando Usar Job Array

Ideal para:

  • Processamento de muitos arquivos independentes

  • Varredura de parâmetros (sweep)

  • Simulações de Monte Carlo

  • Análise de dados embaralhável (embarrassingly parallel)

  • Bootstrapping e validação cruzada

Não recomendado para:

  • Jobs com dependência simultânea entre si

  • Comunicação entre jobs

  • Problemas que exigem sincronização

Sintaxe Básica

#!/bin/bash
#SBATCH --array=1-100
#SBATCH -n 1
#SBATCH -t 01:00:00

echo "Meu índice é $SLURM_ARRAY_TASK_ID"

Formatos de Array

  1. Intervalo simples: --array=1-100 (índices 1 a 100)

  2. Lista específica: --array=1,5,10,20,50

  3. Com passo: --array=1-100:5 (1,6,11,…,96)

  4. Com limite de simultâneos: --array=1-1000%50 (máximo de 50 jobs rodando ao mesmo tempo)

Exemplos Práticos

Exemplo 1: Processamento de Múltiplos Arquivos

Suponha que você tem 100 arquivos de entrada nomeados dados_1.dat, dados_2.dat, …, dados_100.dat.

processa_array.sh
#!/bin/bash
#SBATCH -J processa_dados
#SBATCH --array=1-100
#SBATCH -n 1
#SBATCH -t 02:00:00
#SBATCH --mem=4G
#SBATCH --output=logs/array_%A_%a.out
#SBATCH --error=logs/array_%A_%a.err

# Variáveis do job array
# %A = Job ID do array
# %a = Task ID (índice)

mkdir -p resultados/

export INPUT="dados_${SLURM_ARRAY_TASK_ID}.dat"
export OUTPUT="resultados/resultado_${SLURM_ARRAY_TASK_ID}.dat"

module load python/3.9
job-nanny python processa.py $INPUT -o $OUTPUT

Exemplo 2: Varredura de Parâmetros

Para testar diferentes combinações de parâmetros:

sweep_array.sh
#!/bin/bash
#SBATCH -J sweep
#SBATCH --array=1-27
#SBATCH -n 1
#SBATCH -t 04:00:00

# Definir combinações de parâmetros
temperatura=(300 310 320 330 340 350 360 370 380)
pressao=(1.0 1.5 2.0)
catalisador=("Fe" "Ni" "Co")

# Calcular índices
i_temp=$(( ($SLURM_ARRAY_TASK_ID - 1) / 3 / 3 ))
i_press=$(( ($SLURM_ARRAY_TASK_ID - 1) / 3 % 3 ))
i_cat=$(( ($SLURM_ARRAY_TASK_ID - 1) % 3 ))

T=${temperatura[$i_temp]}
P=${pressao[$i_press]}
CAT=${catalisador[$i_cat]}

export INPUT="template.in"
export OUTPUT="resultados/T${T}_P${P}_${CAT}/"

# Substituir parâmetros no arquivo de entrada
sed -e "s/TEMPERATURA/$T/g" \
    -e "s/PRESSAO/$P/g" \
    -e "s/CATALISADOR/$CAT/g" \
    template.in > input_${SLURM_ARRAY_TASK_ID}.in

job-nanny ./simular input_${SLURM_ARRAY_TASK_ID}.in

Exemplo 3: Job Array com Limite de Simultâneos

Para não sobrecarregar o sistema:

array_limitado.sh
#!/bin/bash
#SBATCH -J limitado
#SBATCH --array=1-1000%50   # Máximo 50 jobs simultâneos
#SBATCH -n 1
#SBATCH -t 01:00:00

# Processamento aqui
./meu_programa input_${SLURM_ARRAY_TASK_ID}.dat

Exemplo 4: Job Array com Dependências

Processamento em duas etapas:

# Submeter o array de processamento
JOBID=$(sbatch --parsable --array=1-100 processa_array.sh)

# Submeter job de pós-processamento (só após todos terminarem)
sbatch --dependency=afterok:$JOBID pos_processamento.sh

pos_processamento.sh:

pos_processamento.sh
#!/bin/bash
#SBATCH -J pos
#SBATCH -n 1
#SBATCH -t 01:00:00

# Coletar todos os resultados e gerar sumário
cat resultados/resultado_*.dat > todos_resultados.dat
python gera_estatisticas.py todos_resultados.dat

Variáveis de Ambiente

Variável

Descrição

Exemplo

$SLURM_ARRAY_JOB_ID

ID do job array

123456

$SLURM_ARRAY_TASK_ID

Índice da tarefa atual

42

$SLURM_ARRAY_TASK_COUNT

Número total de tarefas

100

$SLURM_ARRAY_TASK_MIN

Índice mínimo

1

$SLURM_ARRAY_TASK_MAX

Índice máximo

100

Monitoramento de Job Arrays

Ver todos os jobs do array

squeue -u $USER -t PD,R -o "%.18i %.9P %.8j %.8u %.2t %.10M %.6D %R"

Exemplo de saída:

JOBID       PARTITION         NAME  USER  ST        TIME  NODES  NODELIST
2940077_1      medium   submit_job  joao   R  2-06:11:48      1  node032
2940077_2      medium   submit_job  joao   R  2-04:31:51      1  node050
2940077_3      medium   submit_job  joao   R  2-03:48:25      1  node040
2940077_4      medium   submit_job  joao  PD        0:00      1  (Priority)
2940077_5      medium   submit_job  joao  PD        0:00      1  (Priority)

Cancelar um job array

# Cancelar tarefa específica
scancel 2940077_42

# Cancelar todo o array
scancel 2940077

# Cancelar todas as tarefas pendentes do array
scancel -t PD 2940077

Ver detalhes de uma tarefa

scontrol show job 2940077_42

Limitações

  • Máximo de jobs por array: 1000 (configuração atual do GridUnesp)

  • Máximo de jobs simultâneos: Controlado por %N no array

  • Recursos por job: Cada tarefa do array pode ter suas próprias requisições

  • Nomes de arquivos: Use %A (job array ID) e %a (task ID) para evitar conflitos

Atenção

Atualmente o GridUnesp está configurado para aceitar no máximo 1000 jobs por array.

Boas Práticas

  1. Organize os arquivos de saída

    #SBATCH --output=logs/array_%A_%a.out
    #SBATCH --error=logs/array_%A_%a.err
    
    mkdir -p logs resultados
    
  2. Limite de jobs simultâneos

    #SBATCH --array=1-1000%50   # Não sobrecarrega o sistema
    
  3. Teste com um subconjunto primeiro

    #SBATCH --array=1-10   # Teste com 10 jobs antes de 1000
    
  4. Use nomes significativos

    #SBATCH -J sweep_temp_pressao
    
  5. Monitore o progresso

    squeue -u $USER | grep "seu_job" | wc -l   # Contar jobs ativos
    

Comparação: Job Array vs Jobs Individuais

Comparação: Job Array vs Jobs Individuais

Aspecto

Job Array

Jobs Individuais

Submissão

1 comando

N comandos

Gerenciamento

Centralizado

Disperso

Dependências

Fácil (afterok:JOBID)

Complexo

Cancelamento

1 comando ou seletivo

N comandos

Limite de jobs

1000 por array

10000 no total

Organização

Automática

Manual

Ver também