Melhorando o Script de Submissão

Esta seção tem o intuito de detalhar a construção de um script de submissão de job. Para isso, vários exemplos e opções de parâmetros serão mostrados.

Opções do SBATCH

O SBATCH é uma instrução necessária do Slurm. Eis algumas referências:

A tabela abaixo mostra alguns dos parâmetros do sbatch.

Parâmetro

Abreviação

Significado

–time

-t

Tempo máximo de execução (min, min:seg, horas:min:seg, dias-horas)

–cpus-per-task

-c

Número de CPUs por processo

–ntasks

-n

Número total de processos

–nodes

-N

Número mínimo de worker nodes

–output

-o

Arquivo com o stdout (mensagens de saída)

–error

-e

Arquivo com o stderr (mensagens de erro)

–mem

Memória por nó em MB

–mem-per-cpu

Memória por CPU em MB

Script job-nanny

Vamos supor que que um usuário chamado Spock (cujo login no GridUnesp seja spock) queira, adaptar seu script (denominado vulcano.sh) para começar a processar simulações de seu projeto de pesquisa. Para isso, ele precisa conhecer mais opções sobre o comando SBATCH e como construir um script de maneira adequada.

Digamos ainda que Spock pretenda executar um script em linguagem Python que denominou de dobra_4.py, o qual lê os arquivos de input energia.in e combustivel.in, e produz o arquivo light-speed.data como resultado. Seu script de submissão tem então o seguinte conteúdo:

#!/bin/bash
#SBATCH -t 24:00:00 -c 4

python dobra_4.py --input=energia.in,combustivel.in

Algumas observações sobre esse script:

  • Como sabe que a execução do script dobra_4.py não deverá demorar mais do que 1 dia, requistou o tempo máximo de processamento de 24 horas (-t 24:00:00).

  • Solicitou ainda a alocação de 4 CPUs (-c 4) para realizar o processamento desse job.

  • Ao fim, resolveu utilizar uma versão do Python que ele próprio instalou (/home/spock/installations/bin/python).

Perigo

Aqui já é possível identificar alguns problemas no script de submissão:

  • Não foram informados os arquivos de input nem de output.

  • Também não foi informado o script job-nanny.

  • Também não foram informadas as variáveis de ambiente para o Python a ser usado.

O script job-nanny serve para evitar que as aplicações científicas façam leitura e escrita diretamente na partição /home/. Uma vez que o job é submetido (a partir do /home/) e começa a ser processado pelos worker nodes (nós de processamento), a leitura e escrita em disco deve ser feita em uma partição distinta do /home/. Cabe ao scritp job-nanny escolher qual será essa partição (a depender das configurações do script de submissão). Do contrário, os worker node realizarão leitura e escrita diretamente no disco do /home/, levando a uma sobrecarga na rede devido à grande transferência de arquivos entre esta partição e os nós.

Além disso, o job-nanny também verifica outros parâmetros como INPUT e OUTPUT. A importância de informar quais são os arquivos/pastas de input reside no fato de evitar que todos os arquivos do diretório (da pasta) corrente sejam transferidos para a partição escolhida. Não se deve transferir arquivos desnecessários, que não farão parte da execução da simulação. Bem como é também importante informar quais são os arquivos/pastas de output pois, a depender da aplicação científica utilizada, muito “lixo” é produzido durante o processamento, não sendo de interesse do usuário ter esses arquivos e, ademais, ao garantir que a menor quantidade de dados possível seja transferida, evita degradar a rede.

Por fim, ao usar um pacote instalado no próprio /home/, é preciso informar ao sistema onde encontrar os binários, libs e/ou headers da instalação. Geralmente isso é feito passando o caminho de variáveis como PATH, LD_LIBRARY_PATY e INCLUDE. Mas pode ser necessário informar várias outras variáveis de ambiente. É preciso verificar as instruções do manual de instalação do pacote.

Com base nas observações acima, um script vulcano.sh ideal para Spock seria:

#!/bin/bash
#SBATCH -t 24:00:00 -c 4

export INPUT="energia.in combustivel.in dobra_4.py"
export OUTPUT="light-speed.data"

export PATH=/home/spock/installations/bin:$PATH
export LD_LIBRARY_PATY=/home/spock/installations/lib:$LD_LIBRARY_PATY
export INCLUDE=/home/spock/installations/include:$INCLUDE

job-nanny python dobra_4.py --input=energia.in,combustivel.in

Neste exemplo, estão sendo passados os arquivos energia.in, combustivel.in e dobra_4.py como INPUT, e light-speed.data como OUTPUT dentro das aspas dupla. Havendo mais de um arquivo de input/output, deve-se separar os nomes por espaço em branco.

Digamos agora que Spock tenha decidido usar o pacote Python que instalou num ambiente Conda (veja a Seção Instalação via comandos Conda). Neste caso, o script de submissão teria o seguinte conteúdo:

#!/bin/bash
#SBATCH -t 24:00:00 -c 4
#SBATCH --mail-user=spock.vulcano@unesp.br ---mail-type=END,FAIL

export INPUT="energia.in combustivel.in dobra_4.py"
export OUTPUT="light-speed.data"

module load anaconda3
source activate startrek

job-nanny python dobra_4.py --input=energia.in,combustivel.in

Note que não houve necessidade de informar as variáveis de ambiente já que bastou ativar o ambiente Conda anteriormente criado.

Note também que, desta vez, Spock decidiu incluir seu e-mail (spock.vulcano@unesp.br) para ser informado quando a simulação finalizar com sucesso (END) ou caso seja cancelado devido a alguma falha (FAIL).

Dica

Caso queira saber mais opções do parâmetro ---mail-type, consulte a página do SBATCH.

Parâmetros do job-nanny

O script job-nanny identifica os seguintes parâmetros:

Parâmetro

Valor padrão

Significado

INPUT

“*”

Arquivos copiados para a área temporária para iniciar a simulação.

OUTPUT

“*”

Arquivos copiados de volta para a pasta inicial (no /home/) ao fim da simulação.

CHECKPOINT

“$OUTPUT”

Arquivos copiados sistematicamente para a pasta inicial.

WAIT_CHECKPOINT

“10800” = 3horas

Intervalo entre a cópia dos arquivos de checkpoint, em segundos.

VERBOSE

“0” = False

Controla se informações sobre as operações do próprio script devem ser impressas no stdout

CHECKPOINT_FUNC

Avançado: Usado apenas em casos específicos onde é necessário realizar alguma operação antes do checkpoint. Consule VASP

LARGE_FILES

“false”

Suporte a arquivos grandes. Para ponto de montagem no /store/, usar LARGE_FILES=”true”.

SHARED_FS

Utiliza um sistema de arquivos compartilhado (útil para aplicações MPI). Se SHARED_FS=”true”, é utilizado o ponto de montagem no /store/.

Sempre que a simulação utilizar MPI com Memória Distribuída entre 2 ou mais nós, ou LARGE_FILES=”true”, ou SHARED_FS=”true”, os jobs serão executados a partir da partição /store/. Para informações sobre a utilização das partições /home/, /tmp/ ou /store/, consulte a seção Informações sobre o Storage.

Supondo que o usuário queira informar no parâmetro INPUT apenas 5 arquivos denominados

  • input_01.txt

  • input_02.txt

  • process.dat

  • file_a.csv

  • file_b.csv

e que não se importe em receber todos os arquivos de output e, ainda, gostaria que os resultados da simulação fossem sincronizados com seu /home/ a cada hora (em vez do padrão de 3 horas), o script de submissão poderia então ser configurado assim:

export INPUT="input_*.txt process.dat file*"
export OUTPUT="*"
export WAIT_CHECKPOINT="3600"

Sistema de Filas

O cluster está dividido em filas, de forma a organizar os processos e equilibrar o tempo de espera com o tempo de execução. Cada fila significa que o job não ficará processando por um tempo maior do que aquele que foi solicitado. A tabela a seguir mostra o tempo máximo de processamento em cada fila.

Fila

Limite de execução

short

24 horas (padrão)

medium

7 dias

long

30 dias

Nenhum processo poderá alocar um recurso por mais de 30 dias.

Importante

Cabe ao usuário informar o tempo máximo de processamento do seu job. Caso não informe, a simulação será executada até atingir o prazo padrão (24 horas). E caso o prazo limite seja atingido e o processamento não tenha finalizado, o job é automaticamente CANCELADO por TIMEOUT.

Eis alguns exemplos:

  • Job será processado na fila short por até 50 minutos

#SBATCH -t 50:00
  • Job será processado na fila short por até 23 horas

#SBATCH -t 23:00:00
  • Job será processado na fila medium por até 50 horas (2 dias e 2 horas)

#SBATCH -t 50:00:00
  • Job será processado na fila medium por até 5 dias e 10 horas

#SBATCH -t 5-10
  • Job será processado na fila long por até 12 dias

#SBATCH -t 12-00
  • Job será processado na fila long por até 30 dias

#SBATCH -t 30-00
  • Não serão alocados recursos pois solicitou mais do que 30 dias (45 dias, na verdade). A execução desse job nunca será inicializada pelo Slurm.

#SBATCH -t 45-00

Recomenda-se que processos nas filas medium e long tenham sistemas de checkpoint pois a possibilidade de falha aumenta proporcionalmente ao tempo necessário para a execução. Também recomenda-se que essas simulações sejam testadas antes com processos na fila short (veja seção Otimizando o Desempenho).

Nota

Talvez algum usuáro poderia se perguntar se não seria suficiente informar o tempo máximo permitido em cada fila, ou seja, 24 horas, 7 dias ou 30 dias, em vez de se preocupar com o tempo máximo que acredita que seja necessário.

Contudo, vale ressaltar que quantos mais recursos são solicitados, maior o tempo que o job do usuário poderá ficar esperando até que esses recursos sejam finalmente disponibilizados. E TEMPO também é um recurso.

Sendo assim, podemos concluir que há uma certa “beleza” em fazer uma otimização do tempo necessário a ser alocado para o job.

Informações sobre o Storage

O GridUnesp possui vários storages (partições) para “armazenar” os arquivos dos usuários, sejam eles de entrada, saída ou temporários (gerados durante o processamento do job). Durante o processamento, o programa em exeução poderá manipular arquivos localizados em diferentes pontos de montagem. É fundamental que o usuário entenda cada um deles.

Perigo

A palavra armazenar acima está entre aspas porque o usuário não deve pensar que pode usar o cluster do GridUnesp como lugar para guardar dados. A capacidade em disco das partições, apesar de significativamente grande, é limitada. Assim, apenas arquivos/pastas estritamente necessários à realização de novas simulação é que podem ser mantidos. Os resultados devem ser movidos para um computador local. Veja mais informações na Seção Manutenção dos Dados.

Abaixo está a lista dos pontos de montagen seguido do seu tamanho e escopo de acesso.

Ponto de Montagem

Tamanho

Escopo

/tmp/

120 GB

Job usando apenas 1 nó e arquivos pequenos

/store/

32 TB

Job usando mais de 1 nó e/ou arquivos grandes

/home/

40 TB

Preparação dos jobs para submissão

A partir daqui, vamos entender em detalhes o uso de cada partição.

Partição: /home/

Este é o único ponto de montagem acessível pelo servidor de acesso (access2.grid.unesp.br). O usuário deve colocar aqui seus arquivos de entrada, assim como é onde serão depositados os arquivos produzidos nas simulações.

Partição: /tmp/

Utilizado para salvar arquivos temporários durante a execução do job. Este diretório é o menor de todos (120 GB) e é um disco localizado dentro do nó de processamento (worker node). Ou seja, se 2 jobs estão sendo executos em nós diferentes, cada processo irá acessar um /tmp/ diferente. Não há compartilhamento entre os /tmp/ de diferentes nós. Nos casos em que o job utiliza apenas 1 nó e, além disso, os arquivos de input e output são relativamente poucos e pequenos (não mais do que unidades de GB), então a partição /tmp/ é a melhor opção.

O vídeo abaixo ilustra o que ocorre com o fluxo de dados ao usar a partição /tmp/.

Vamos supor então que que um usuário queira executar um aplicação científica (hipotética) chamada test-Covid que seja capaz de trabalhar com várias threads em um único nó. Além disso, após estudos de optimização, vamos supor que o usuário saiba que a simulação possa ter maior performance alocando 6 CPUs para cada processo (-c 6) e que terá duração máxima de 5 dias (-t 5-00). O script de submissão hipotético seria algo como:

#!/bin/bash
#SBATCH -t 5-00 -c 6

export INPUT="teste-pcr.in teste-sangue.in"
export OUTPUT="casos-positivos.out obitos.out"

module load anaconda3
source activate sarscov2

job-nanny test-Covid -in=teste-pcr.in,teste-sangue.in -out=casos-positivos.out,obitos.out

Analiando em detalhes o que ocorre com o fluxo de dados, sabemos ao menos que o script job-nanny irá copiar os arquivos de input para a partição /tmp/ de um dos nós que foi alocado ao job, sendo lidos pelo programa test-Covid (instalado no /home/ do usuário via ambiente Conda) e cujo processamento será feito nesse worker node especifico. Os outpus serão temporariamente escritos na partição /tmp/ e copiados para o /home/ a cada 3 horas.

Já em caso de processos com múltiplos nós (ex: MPI), o usuário deve utilizar a partição /store/.

Partição: /store/

Caso a partição /tmp/ não seja suficiente (devido ao seu tamanho limitado ou ao escopo do trabalho), então a alternativa é que os arquivos temporários utilizem a partição /store/. Ela possui um escopo maior, sendo visível por todos os nós em que o job está em sendo executado. Seu espaço também é maior, contendo atualmente 32 TB. Assim, caso o script de submissão contenha instruções para uso de vários processos ou de vários nós, o programa em execução irá usar a partição /store/.

O vídeo abaixo ilustra o que ocorre com o fluxo de dados ao usar a partição /store/.

Vamos supor então que que um usuário queira executar um aplicação científica (hipotética) chamada test-Covid que seja capaz de trabalhar com vários processos espalhados por vários nós. Digamos ainda que o usuário queira, para isso, usar 12 processos (-n 12) espalhados em 3 nós (-N 3). Além disso, após estudos de optimização, vamos supor que o usuário saiba que a simulação possa ter maior performance alocando 2 CPUs para cada processo (-c 2) e que terá duração máxima de 3 dias (-t 3-00). O script de submissão hipotético seria algo como:

#!/bin/bash
#SBATCH -t 3-00 -n 12 -N 3 -c 2

export INPUT="teste-pcr.in teste-sangue.in"
export OUTPUT="casos-positivos.out obitos.out"
export WAIT_CHECKPOINT="5400"

module load intel/compilers/2017
module load intel/mpi/2017
module load anaconda3
source activate sarscov2

job-nanny test-Covid -in=teste-pcr.in,teste-sangue.in -out=casos-positivos.out,obitos.out

Analiando em detalhes o que ocorrerá com o fluxo de dados, sabemos ao menos que o script job-nanny irá copiar os arquivos de input para a partição /store/, sendo lidos pelo programa test-Covid (instalado no /home/ do usuário via ambiente Conda) e cujo processamento será feito por 3 worker nodes. Os outpus serão temporariamente escritos na partição /store/ e copiados para o /home/ a cada 1 hora e meia (5400 segundos). Ademais, para os processos serem espalhados em vários nós a partir do conceito de Memória Distribuída, foram usadas as ferramentas MPI da Intel através dos módulos.

Por fim, é válido ainda informar que os 12 processos não serão espalhados igualmente para cada nó (4 processos por nó). Isto é, a maneira do Slurm distribuir os processos nos 3 worker nodes poderia ser 4,4,4, assim como: 2,6,4; 3,3,6; 1,7,4; 8,2,2; etc. E como foram solicitadas 2 CPUs para cada processo, o Slurm alocou um total de 24 CPUs para essa simulação (2 CPUs para cada um dos 12 processos).

Nota

Em algumas situações (como quando a fila de jobs está consideravelmente grande), pode ser mais interessante ao usuário não especificar uma quantidade exata de worker nodes, mas delimitar quantidades mínima e máxima, deixando a decisão para o escalonadador do sistema (Slurm). Como exemplo, digamos que o usuário deseje espalhar 18 processos entre 2 e 4 nós. Isso poderia ser feito da seguinte maneira:

#!/bin/bash
#SBATCH -n 18 -N 2-4

Quando apenas um único valor é especificado, o sistema identifica as quantidades mínima e máxima de nós como sendo as mesmas: -N 4, por exemplo, é equivalente a -N 4-4.