07 ‐ Submeter Jobs - arcarneiro/teste-doc-sdumont GitHub Wiki
O procedimento usual para a submissão de jobs no SDumont compreende:
- Compilar a aplicação dentro do HOMEDIR, utilizando os compiladores desejados
- Criar um script de submissão, configurando os parâmetros necessários para a execução do Job
- Copiar os arquivos necessários (script, executável, bibliotecas, dados de entrada, etc) para dentro da área de SCRATCH, pois a área de HOMEDIR não é acessível pelos nós computacionais
- Submeter o script com o comando sbatch
- Verificar os arquivos de saída
- Nos scripts (jobs em batch) os parâmetros do SLURM devem ser precedidos por #SBATCH como será visto mais adiante.
- Os scripts não precisam ser executáveis e nem precisam possuir uma extensão (.sh, .bash, etc), mas precisam iniciar com a linha #!/bin/bash.
- Ressubmissão automática de Jobs: O comportamento padrão do Slurm é de reiniciar/ressubmeter um job quando ocorre uma falha em um dos nós alocados. Para desabilitar essa funcionalidade, basta incluir o parâmetro abaixo no script:
#SBATCH --no-requeue
Apresentamos abaixo alguns templantes de scripts, que podem ser utilizados como modelo e adaptados para as necessidades. A maioria dos exemplos executam o benchmark NAS Parallel Benchmarks.
OBS: Ao longo da documentação e dos scripts de exemplo, o termo "Tarefas MPI" possui a mesma conotação de "processos MPI". Como exemplo, ao iniciar a execução de uma aplicação paralela com o comando mpirun -np 4, podemos dizer que esta executará 4 tarefas MPI ou 4 processos MPI.
#!/bin/bash
#SBATCH --nodes=1 #Para jobs seriais, deve utilizar sempre apenas um nó!
#SBATCH --ntasks=1 #Para jobs seriais, deve utilizar sempre apenas uma tarefa!
#SBATCH -p FILA #Fila (partition) a ser utilizada
#SBATCH -J JOB #Nome job
#Exibe os nós alocados para o Job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
cd $SLURM_SUBMIT_DIR
#Configura os compiladores
#-------------------------#
## 1) Carregar o módulo do compilador utilizado, conforme indicado na seção "Compiladores e MPI"
module load <compilador>/<versão>
## 2) Carregar o módulo da aplicação, caso necessário
module load <aplicacao>/<versão>
#Configura o executavel
EXEC=/scratch/CAMINHO/PARA/O/EXECUTAVEL
#exibe informações sobre o executável
/usr/bin/ldd $EXEC
#Inicia a execucao
srun $EXEC
OBS: Para aplicações seriais, não é necessário utilizar o comando srun para iniciar a aplicação, podendo executá-la diretamente na última linha do script de submissão (basta apenas remover o comando srun da última linha do script acima, deixando apenas o nome do binário a ser executado: $EXEC).
#!/bin/bash
#SBATCH --nodes=1 #Numero de Nós
#SBATCH --ntasks=1 #Numero de tarefas
#SBATCH -p sequana_cpu #Fila (partition) a ser utilizada
#SBATCH -J exemplo_1_serial #Nome job
#Exibe os nós alocados para o Job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
cd $SLURM_SUBMIT_DIR
#Configura os compiladores GNU, versão 9.11
module load gcc/4.9.3_sequana
#Configura o executavel
EXEC=/scratch/app/NPB3.3.1-MZ/bin/cg.C.x
#exibe informações sobre o executável
/usr/bin/ldd $EXEC
#Inicia a execucao
srun $EXEC
Para submeter o script, utilizar o comando sbatch:
sbatch /caminho/do/script.srm
#!/bin/bash
#SBATCH --nodes=N #Numero de Nós
#SBATCH --ntasks-per-node=TPN #Numero de tarefas por Nó
#SBATCH --ntasks=T #Numero total de tarefas MPI
#SBATCH -p FILA #Fila (partition) a ser utilizada
#SBATCH -J JOB #Nome job
#Exibe os nós alocados para o Job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
cd $SLURM_SUBMIT_DIR
#Configura os compiladores
#-------------------------#
## 1) Carregar o módulo do MPI utilizado, conforme indicado na seção "Compiladores e MPI"
module load <MPI>/<versão>
## 2) Carregar o módulo da aplicação, caso necessário
module load <aplicacao>/<versão>
#Configura o executavel
EXEC=/scratch/CAMINHO/PARA/O/EXECUTAVEL
#exibe informações sobre o executável
/usr/bin/ldd $EXEC
#Inicia a execucao
srun $EXEC
Utilizando o OpenMPI 4.1.4, alocando 4 nós, utilizando 24 tarefas MPI por nó, totalizando 96 tarefas, e alterando o limite de tempo.
*OBS: Por padrão, quando não especificado, o Slurm configura o WallCLock do job como a metade do limite da fila. Para alterar esse valor, basta utilizar o parâmetro --time=HH:MM:SS
Script rodarmpi.srm
#!/bin/bash
#SBATCH --nodes=4 #Numero de Nós
#SBATCH --ntasks-per-node=24 #Numero de tarefas por Nó
#SBATCH --ntasks=96 #Numero total de tarefas MPI
#SBATCH -p sequana_cpu #Fila (partition) a ser utilizada
#SBATCH -J NPB-MZ-sp-intelmpi-24 #Nome job
#SBATCH --time=01:00:00 #Altera o tempo limite para 1 hora
#Exibe os nós alocados para o Job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
cd $SLURM_SUBMIT_DIR
#Configura os compiladores
module load openmpi/gnu/4.1.4_sequana
#Configura o executavel
EXEC=/scratch/app/NPB3.3.1-MZ/bin/bt-mz.C.x
#exibe informações sobre o executável
/usr/bin/ldd $EXEC
srun $EXEC
Submeter o job através do comando:
sbatch rodarmpi.srm
Exemplos de script para aplicações que possuem paralelismo apenas através de Threads OpenMP, sem a capacidade de se dividir e utilizar múltiplos nós.
Utilizando os compiladores Intel e executando 48 threads. Para configurar o número de threads, é necessário configurar o parâmetro --cpus-per-task do SLURM no script de submissão.
O número nós e o número total de tarefas deve ser igual a 1.
Script rodaropenmp.srm
#!/bin/bash
#SBATCH --nodes=1 #Numero de Nós deve ser igual a 1
#SBATCH --ntasks-per-node=1 #Numero de tarefas por Nó deve ser igual a 1
#SBATCH --ntasks=1 #Numero total de tarefas deve ser igual a 1
#SBATCH --cpus-per-task=48 #Numero de threads
#SBATCH -p sequana_cpu_dev #Fila (partition) a ser utilizada
#SBATCH -J NPB-MZ-sp-openmp-intel #Nome job
#Exibe os nós alocados para o Job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
cd $SLURM_SUBMIT_DIR
#Configura os compiladores
module load intel_psxe/2020_sequana
#exibe informações sobre o executável
EXEC=/scratch/app/NPB3.3.1-MZ/bin/sp-mz.C.openmp-intel.x
/usr/bin/ldd $EXEC
#Configura o numero de threads OpenMP com o valor passado para a variavel --cpus-per-task
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
srun -c $SLURM_CPUS_PER_TASK $EXEC
Submeter o job através do comando:
sbatch rodaropenmp.srm
Scripts para aplicações que utilizam dois níveis de paralelismo: MPI + OpenMP.
Utilizando os compiladores e MPI Intel, alocando 4 nós, distribuindo 1 processo MPI por nó, que abrirá 48 threads cada um.
- Número de máquinas = 4 -> configurado através do parâmetro --nodes.
- Número de tarefas MPI por Nó = 1 -> configurado através do parâmetro --ntasks-per-node.
- Número total de tarefas MPI = 4 -> configurado através do parâmetro --ntasks, representando nodes * ntasks-per-node.
- Número de threads que cada mpi abrirá = 48 -> configurado através do parâmetro --cpus-per-task.
Script rodarmpi+openmp.srm
#!/bin/bash
#SBATCH --nodes=4 #Numero de Nós
#SBATCH --ntasks-per-node=1 #Numero de tarefas por Nó
#SBATCH --ntasks=4 #Numero total de tarefas MPI
#SBATCH --cpus-per-task=48 #Numero de threads por tarefa MPI
#SBATCH -p sequana_cpu_dev #Fila (partition) a ser utilizada
#SBATCH -J NPB-MZ-sp-intel-hybrid-4 #Nome job
#Exibe os nos alocados para o Job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
cd $SLURM_SUBMIT_DIR
#Configura os compiladores
module load intel_psxe/2020_sequana
#exibe informaçoes sobre o executavel
EXEC=/scratch/app/NPB3.3.1-MZ/bin/sp-mz.C.intelmpi-hybrid.4
/usr/bin/ldd $EXEC
#configura o numero de threads, de acordo com o parametro definido no SLURM
export OMP_NUM_THREADS=$SLURM_CPUS_PER_TASK
srun -c $SLURM_CPUS_PER_TASK $EXEC
Submeter o job através do comando:
sbatch rodarmpi+openmp.srm
É possível, dentro de um único job (script) executar múltiplas instâncias de uma mesma aplicação ou múltiplas aplicações distintas.
Dentro do conjunto solicitado de recursos (número de nós e de cores), é possível fazer uma divisão e iniciar a execução simultânea.
Por exemplo, solicitar 4 nós e executar:
- Uma aplicação em cada nó distinto
- Duas aplicações, cada uma executando em 2 nós
- Três aplicações, uma executando em dois nós e as outras duas executando em um nó cada
Alocando 4 nós, mas executando duas instâncias de uma mesma aplicação MPI, de forma independente e simultânea. Cada execução utilizará 2 nós e um total de 96 processos.
Script rodar.srm
#!/bin/bash
#SBATCH --nodes=4 #Numero de Nós
#SBATCH --ntasks-per-node=48 #Numero de tarefas por Nó
#SBATCH --ntasks=192 #Numero total de tarefas MPI
#SBATCH -p sequana_cpu_dev #Fila (partition) a ser utilizada
#SBATCH -J NPB-MZ-bt-Multi #Nome job
#Exibe os nos alocados para o Job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
cd $SLURM_SUBMIT_DIR
#Configura os compiladores
module load openmpi/gnu/4.1.4_sequana
#Configura o executavel
EXEC=/scratch/app/NPB3.3.1-MZ/bin/bt-mz.C.x
/usr/bin/ldd $EXEC
#configura o numero de threads como 1
export OMP_NUM_THREADS=1
srun --nodes=2 --ntasks=96 $EXEC > out.exec.1.txt 2>&1 &
srun --nodes=2 --ntasks=96 $EXEC > out.exec.2.txt 2>&1 &
wait
Submeter o job através do comando:
sbatch rodar.srm
OBS:
- Necessário a inclusão do & ao final da linha de execução da aplicação, para poder iniciar em segundo plano.
- Necessário a inclusão do comando wait ao final do script, para aguardar a finalização da execução das aplicações em segundo plano. Do contrário, o script finalizaria a execução do job antes de obter os resultados.
- Necessário ajustar os parâmetros --nodes e --ntasks, na linha do srun, para poder dividir os recursos alocados (4 nós e um total de 192 tarefas) entre as execuções das aplicações.
Para submeter jobs interativos no SDumont, é necessário utilizar o comando salloc, solicitando os recursos a serem utilizados. Quando o salloc consegue alocar os recursos solicitados para o job, ele inicia uma nova sessão, que permite ao usuário executar a aplicação diretamente (através do srun), ou acessar o nó via ssh, realizar as suas tarefas localmente e executar a aplicação (através do mpirun/mpiexec).
Quando a aplicação iniciar a execução, a saída será mostrada no STDOUT, que geralmente é a tela/terminal.
- IMPORTANTE: Se não houver recurso disponível para iniciar o JOB, o prompt do terminal ficará bloqueado, aguardando os recursos ficarem disponíveis.
- IMPORTANTE: Sempre executar o comando exit para finalizar a sessão e terminar o job.
Submetendo um job interativo, utilizando o Intel MPI.
salloc --nodes=2 --ntasks-per-node=12 --ntasks=24 -p sequana_cpu_dev -J NPB-MZ-interativo
#SLURM exibirá informações sobre a alocação dos recursos
salloc: Pending job allocation NNNNNNNNN
salloc: job NNNNNNNNN queued and waiting for resources
salloc: job NNNNNNNNN has been allocated resources
salloc: Granted job allocation NNNNNNNNN
salloc: Waiting for resource configuration
salloc: Nodes sdumont[YYYYY-ZZZZZ] are ready for job
#verificar quais nós foram alocados para o job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
#carregar as bibliotecas
module load intel_psxe/2016
#executa a aplicação
srun -n 24 /scratch/app/NPB3.3.1-MZ/bin/sp-mz.C.intelmpi.24
#encerra a sessão interativa e termina o job
exit
Submetendo um job interativo, alocando 4 nós e acessando diretamente o nó. Será utilizado o OpenMPI 2.0.
Nesse exemplo, vamos supor que o Slurm alocou para o job os nós sdumont6000, sdumont6001, sdumont6002 e sdumont6003.
salloc --nodes=4 --ntasks-per-node=6 --ntasks=24 -p sequana_cpu_dev -J Interativo
#SLURM exibirá informações sobre a alocação dos recursos
salloc: Pending job allocation NNNNNNNNN
salloc: job NNNNNNNNN queued and waiting for resources
salloc: job NNNNNNNNN has been allocated resources
salloc: Granted job allocation NNNNNNNNN
salloc: Waiting for resource configuration
salloc: Nodes sdumont[6000-6003] are ready for job
#verificar quais nós foram alocados para o job
echo $SLURM_JOB_NODELIST
#retornará algo como sdumont[6000-6003]
nodeset -e $SLURM_JOB_NODELIST
#retornará algo como sdumont6000 sdumont6001 sdumont6002 sdumont6003
#acessar o primeiro nó alocado
ssh sdumont6000
#carregar as bibliotecas
[usuario@sdumont6000 ~]$ module load openmpi/2.0.4.2
[usuario@sdumont6000 ~]$ module load gcc/6.5
#pode realizar a compilação da aplicação
[usuario@sdumont6000 ~]$ cd $SCRATCH/CODIGO
[usuario@sdumont6000 CODIGO]$ make ....
#executa a aplicação, utilizando o mpiexec
[usuario@sdumont6000 CODIGO]$ mpiexec -x LD_LIBRARY_PATH \
--host sdumont6000,sdumont6001,sdumont6002,sdumont6003 -np 24 -npernode 6 ${PWD}/executavel
#encerra a sessão no nó sdumont6000
[usuario@sdumont6000 ~]$ exit
#encerra a sessão interativa e termina o job
exit
Conforme descrito na seção "06 ‐ Gerenciador de filas", as filas sequana_gpu* permitem o compartilhamento do nó por múltiplos jobs (até 4). Para submeter jobs para essas filas, é necessário fazer utilização do GRES do SLURM.
- Para garantir o melhor uso dos recursos, o parâmetro --exclusive não deve ser utilizado!
- Embora os nós sejam de uso compartilhado, os recursos alocados para o job são de uso exclusivo (processadores, memória e GPU)
- Cada nó computacional do SDumont expansão (Sequana X1120) possui 4 aceleradores NVIDIA V100, 48 núcleos CPU e 384GB de memória RAM. Em cada nó, é possível executar até 4 jobs simultaneamente, cada um usando os recursos solicitados de forma independente.
- Para alocar uma ou mais GPUs, é obrigatório especificar a quantidade de aceleradores (parâmetros --gpus, --gpus-per-node, --gpus-per-socket, --gpus-per-task).
- Caso não seja informada a quantidade de GPU's, o job não entrará em execução e ficará pendente em fila com a REASON QOSMinGRES.
- Quando não for informado a quantidade de cores desejados (parâmetros --cpus-per-gpu, -n, --ntasks, --ntasks-per-node, --ntasks-per-socket, --tasks-per-node), o SLURM reservará 12 cores por GPU solicitada.
- Quando o usuário não especificar a quantidade de memória a ser utilizada (parâmetros --mem-per-gpu, --mem, --mem-per-cpu), o SLURM reservará 8GB por core solicitado.
- Por padrão, se não for especificada a quantidade de cores e memória, para cada GPU solicitada serão alocados 12 cores e 96GB de memória RAM.
- A GPU (unidade) não é compartilhável, portanto ao ser alocada para um job, nenhum outro job conseguirá utilizá-la.
- Parâmetros do slurm para alocações referentes a GPU
- --gpus=n: Número total de GPUs solicitadas para o job
- --gpus-per-node=n: Número de GPUs solicitadas para cada nó alocado
- --gres=gpu:n: Número de GPUs solicitadas por nó (o mesmo que a combinação de --gpus=n --gpus-per-node=n)
- --gpus-per-socket=n: Número de GPUs solicitadas para cada socket alocada
- --gpus-per-task=n: Número de GPUs solicitadas para cada tarefa alocada
- --cpus-per-gpu=n: Número de CPUs solicitadas para cada GPU alocada (Valor padrão: 12 CPUs para cada GPU alocada)
- --mem-per-gpu=n: Memória RAM solicitada para cada GPU alocada (Valor padrão: 8GB para cada CPU alocada)
- O número total de GPUs não é necessariamente dividido em partes iguais entre os nós alocados. Por exemplo, 8 GPUs solicitadas. O SLURM pode alocar 4 GPUs em um nó, 3 GPUs em outro nó e 1 GPU em um terceiro nó, a depender dos recursos e nós disponíveis. Para definir quantas GPUs devem ser alocadas por nó, deve-se utilizar o parâmetro --gpus-per-node=n ou --gres=gpu:n.
-
ATENÇÃO: Ao utilizar os parâmetros para solicitar os recursos, observar se os valores solicitados estão em conformidade com os recursos disponíveis no(s) nó(s), para não ocorrer incompatibilidade e erro de submissão. Por exemplo, para os parâmetros abaixo:
- --gpus-per-node: Os nós do SDumont expansão possuem 4 GPUs. Ao configurar este parâmetro, se for especificado um número que seja maior do que o disponível nos nós solicitados, ocorrerá o erro “Invalid generic resource (gres) specification” ou “Requested node configuration is not available” ao tentar realizar a submissão.
- --cpus-per-gpu: Os nós do SDumont expansão possuem 48 cores. Ao configurar este parâmetro, deve-se atentar para a quantidade solicitada vs quantidade disponível. Se for especificado um número que seja maior do que o disponível no nó (ex: --gpus-per-node=2 e --cpus-per-gpu=48 totalizando 96 cores), ocorrerá o erro “Invalid generic resource (gres) specification” ou “Requested node configuration is not available” ao tentar realizar a submissão.
- --mem-per-gpu: Os nós do SDumont expansão possuem 384 GB de RAM. Ao configurar este parâmetro, deve-se atentar para a quantidade solicitada vs quantidade disponível. Se for especificado um número que seja maior do que o disponível no nó (ex: --gpus-per-node=4 e --mem-per-gpu=99000, totalizando 396 GB), ocorrerá o erro “Invalid generic resource (gres) specification” ou “Requested node configuration is not available” ao tentar realizar a submissão.
Submetendo um job para fila, alocando 2 nós e 4 GPUs.
Se não informado, por padrão são alocadas 12 CPUs para cada GPU solicitada e 8GB me memória para cada CPU alocada. Neste exemplo, serão alocados 2 nós, 4 GPUs, 48 CPUs e 384GB de memória.
IMPORTANTE: O número total de GPUs não é necessariamente dividido em partes iguais entre os nós alocados. Das quatro GPUs solicitadas, o escalonador pode alocar uma GPU em um nó e 3 GPUs em outro nó. Basta ter recurso disponível na fila. Para definir quantas GPUs devem ser alocadas por nó, utilize o parâmetro --gpus-per-node.
Esse script utiliza um exemplo cuda, compilado com o cuda/11.2_sequana.
#!/bin/bash
#SBATCH --nodes=2 #Numero de Nos
#SBATCH -p sequana_gpu_dev #Fila (partition) a ser utilizada
#SBATCH -J simpleMultiGPU #Nome job
#SBATCH --gpus=4 #Numero total de GPUS
#Exibe os nós alocados para o Job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
cd $SLURM_SUBMIT_DIR
#Configura os Módulos
module load cuda/11.2_sequana
#Exibe as GPUs disponiveis
nvidia-smi
#Configura o executavel
EXEC=/scratch/app/cuda-samples/cuda-11.2-samples/bin/x86_64/linux/release/simpleMultiGPU
#exibe informações sobre o executável
/usr/bin/ldd $EXEC
srun $EXEC
Submetendo um job, alocando 2 nós e 1 GPU em cada nó.
Foram solicitadas 4 cores e 32GB de memória para cada GPU alocada.
Esse script utiliza um exemplo cuda, compilado com openmpi/gnu/4.1.2+cuda-11.2_sequana
#!/bin/bash
#SBATCH --nodes=2 #Numero de Nos
#SBATCH -p sequana_gpu #Fila (partition) a ser utilizada
#SBATCH -J cudaOpenMP #Nome job
#SBATCH --gpus=2 #Numero total de GPUS
#SBATCH --gpus-per-node=1 #Numero de GPUS por no
#SBATCH --cpus-per-gpu=4 #Numero de CPUs por GPU
#SBATCH --mem-per-gpu=32000 #Memoria em GB por GPU
#Exibe os nós alocados para o Job
echo $SLURM_JOB_NODELIST
nodeset -e $SLURM_JOB_NODELIST
cd $SLURM_SUBMIT_DIR
#Configura os Módulos
module load openmpi/gnu/4.1.2+cuda-11.2_sequana
#Exibe as GPUs disponiveis
nvidia-smi
#Configura o executavel
EXEC=/scratch/app/cuda-samples/cuda-11.2-samples/bin/x86_64/linux/release/cudaOpenMP
#exibe informações sobre o executável
/usr/bin/ldd $EXEC
srun $EXEC
A fila gdl utiliza um nó com uma arquitetura especialmente projetada para processamento em Aprendizagem Profunda (Deep Learning), contendo 8 GPUs NVIDIA Tesla V100-16GB com NVLink (total de 40.960 CUDA-core e 5.120 Tensor-core), além de 2 CPUs Intel Xeon Skylake Gold 6148 (20 CPU-core cada) e um total de 384GB de memória RAM (DDR4).
A utilização da fila gdl segue o mesmo padrão das outras filas GPU, podendo ser através de jobs interativos ou através de scripts de submissão, sendo necessário especificar o número de GPU a ser utilizado.