O que é
O Oscar, é um cluster de 42 máquinas, modelo NovaScale da empresa Bull. Ele foi adquirido em um projeto conjunto que envolve os Institutos de Computação, Física e Química da Uff financiado pela FINEP (PROINFRA 2004).
Hardware
O cluster é composto de 42 máquinas, 2 switchs gigabit e um data storage de 14,5 TB. Das 42 máquinas, uma serve para login e compilação de programas, outra manutenção e monitoramento e 40 máquinas para cálculo. Cada uma das 42 máquinas do Cluster possui 2 processadores Intel Xeon quadcore (8 cores), sendo que os 40 nós de cálculo possuem 16 GB memória de RAM, e as 2 máquinas de login e manutenção, 8 GB de RAM. Todas as máquinas são interligadas com switch Gigabit Ethernet.
Software
O cluster é baseado em linux, Red Hat Enterprise Linux Server versão 5.3, ele possui compiladores intel C, C++ e FORTRAN e a biblioteca matemática MKL da Intel. Ele também possui bibliotecas para programação paralela, sendo MPI Intel e MPICH da Bull e a biblioteca OPENMP.
Além dos compiladores e bibliotecas de programação paralela, existem softwares de uso específico, sendo que alguns deles tem capacidade de aproveitar os vários processadores do cluster para resolver os problemas de forma paralela, ou seja, em uma quantidade de tempo menor do que gastaria para resolver o mesmo problema em uma única máquina. Os outros softwares, mesmo não sendo paralelos, podem ser executados pelos seus usuários em várias instâncias ao mesmo tempo, cada uma com uma entrada diferente. Esse tipo de utilização leva a poupar grande quantidade de tempo e possibilita experimentos mais refinados.
Dos softwares instalados até o momento, podem ser listados:
Como ter acesso ao cluster
Um professor ou coordenador de um projeto de pesquisa (lotada aos Institutos de Computação, de Física ou de Química) que desejar usar o cluster deve fazer uma solicitação ao Comitê Gestor ( cg-oscar@ic.uff.br cg-oscar@ic.uff.br ). O solicitante receberá um formulário para preencher e devolver para avaliação pelo comitê.
Login e cópia de arquivos no cluster
O acesso ao cluster se dá através do login ssh (secure shell) em uma máquina específica do cluster chamada de uff0.ic.uff.br. A máquina de login também atende pelo nome oscar.ic.uff.br, que é um apelido para a uff0. O login pode ser feito pelo programa putty no caso do windows e a cópia de arquivos para o cluster pode ser feita via sftp, com programas como o winscp ou filezilla. Cada usuário com uma conta, possui uma pasta no oscar, onde pode colocar seus arquivos e compilar eles e gerar arquivos que serão executados no cluster, e criar novas subpastas.
Os arquivos com dados de entrada, bem como os arquivos fonte, podem ser copiados para o cluster via sftp, ou podem ser criados/editados diretamente na uff0. E possivel abrir janelas do editor ou programas do cluster, usando o comando ssh -X ou o servidor de janelas do windows o xming.
Como compilar programas
Na máquina uff0 do cluster ficam os compiladores. Os usuários, devem compilar seus programas na uff0, e depois colocar seus programas para rodar em uma ou mais das 40 máquinas disponíveis para computação (os nós de computação chamam-se uff2 até uff41. Existe uma máquina chamada uff1, que serve para fins de manutenção).
Exemplos de como compilar programas em C, C++, Fortran, MPI e OpenMP
Compilar um programa em C, usando o compilador Intel:
icc hello.c -o hello
Compilar um programa em FORTRAN, usando o compilador Intel:
ifort hello.for -o hello
Compilar programa em C++:
icpc hello.cpp -o hello
Compilar programa em c com as bibliotecas mpi:
mpicc testempi.c -o testempi
Compilar programa em c++ com mpi
mpiCC testempi.cpp -o testempi
Compilar programa em fortran com mpi:
mpif77 hellompi.f -o hellompif
mpif90 hellompi.f -o hellompif
Compilar programa em c com a biblioteca openmp:
icc testeopenmp2.c -openmp -o testeopenmp2
Como executar os programas
Após ter o programa compilado, para executar ele no cluster, o usuário deve passar por duas etapas:
1 – Solicitar quantas e/ou quais máquinas do cluster ele quer utilizar, através do software de escalonamento. (PBS)
2 – Executar seu programa, nas máquinas que solicitou.
A solicitação de máquinas, e feita via comando “qsub”. Apos isso a solicitacao pode ser imediatamente atendida, ou entrar em uma fila caso as máquinas solicitadas estejam em uso.
Essa página mostra exemplos básicos de como solicitar máquinas do cluster usando o comando qsub do PBS. Para mais detalhes sobre o qsub e outros comandos do PBS consulte o manual do usuário PBS disponível nesse link.
No momento em que o usuário requisitar as máquinas, ele precisa também passar um arquivo de script, que contém os comandos dos programas que ele deseja executar nas máquinas que solicitou.
Submetendo um script em uma máquina qualquer, sendo que todas as 8 cpus da máquina são requisitadas:
qsub -l nodes=1:ppn=8 meu_script
Submetendo um script em uma máquina específica (uff9), requisitando dela 8 cpus:
qsub -l nodes=uff9:ppn=8 meu_script
Submetendo um script em duas maquinas quaisquer, sendo que as duas máquinas precisam ter 8 cpus livres (cada máquina). Como o usuário está requisitando 2x(8 cpus) no total ele terá 16cpus.
qsub -l nodes=2:ppn=8 meu_script
Submetendo um programa em seis máquinas quaisquer, cada uma delas com todas as 8 CPUS disponíveis:
qsub -l nodes=6:ppn=8 meu_script
Submetendo um script em duas máquinas específicas (uff2 e uff9):
qsub -l nodes=uff2:ppn=8+uff9:ppn=8 meu_script
Uma requisição de usuário feita com o comando qsub, é chamada de job. Basicamente o job possui a lista de máquinas que o usuário pediu, e o script com os comandos que o usuário quer executar nessas máquinas.
Dependendo da disponibilidade das máquinas requisitadas no momento em o usuário submete um job, o job pode ser executado imediatamente, ou ficar em uma fila de espera.
No momento em que um job é submetido, ele ganha um número automaticamente (jobid) O jobid pode ser acompanhado pelo usuário. O usuário também pode matar seu job se desejar.
Comandos úteis
Alguns comandos úteis para criação, acompanhamanto e exclusão jobs são:
qsub -l nodes=RECURSOS arquivo_de_script
O qsub cria o job, que é uma solicitação de máquinas onde se deseja executar um conjunto de comandos programas, e o script que contém esses comandos.
qsub -l nodes=RECURSOS -I
O qsub em modo interativo (acrescentando o flag -I (i maiusculo) ao inves de um script), permite ao usuário ter acesso direto as máquinas que ele requisitou. Esse comando é útil para fazer testes de scripts e para depurar scripts que não funcionam. Na prática não é muito usado, pois força pode forçar o usuário a ficar esperando a fila de jobs até que seu job entre em execução.
qstat
O qstat lista os jobs, mostrando detalhes como o dono e o estado do job, que basicamente é R (running) ou Q (queued)
qstat -f jobid
O qstat com o flag -f e o id do job, mostra detalhes sobre o job.
pbsnodes -a
O comando pbsnodes -a lista o estado de todos as maquinas. Mostrando se estao disponiveis, e como as cpus estao ocupadas.
pbsnodes nome_da_maquina
Mostra o estado de uma maquina.
qdel jobid
O qdel exclui um job. O usuário só pode excluir jobs criados por ele mesmo.
Exemplos de scripts
Abaixo seguem 4 exemplos de script para submissão de programas no cluster, e a chamada qsub para cada um dos scripts. O primeiro exemplo trata de um programa sequencial comum. O segundo, várias instâncias de um programa sequencial. O terceiro um programa paralelizavel que roda em uma máquina (programa com mais de uma thread). O quarto trata de um programa paralelizavel em uma ou várias máquinas, por usar ta biblioteca de troca de mensagens MPI.
Exemplo 1
Um script que submete um programa comum sequencial chamado “programa_seq1” e que está na pasta “meus_programas” na pasta home usuário. O nome do arquivo desse script é sequencial_1
Conteúdo do arquivo de script sequencial_1:
#Isso e um comentario, INICIO DO SCRIPT
#o script precisa entrar na pasta onde o programa esta
cd meus_programas
#agora o programa será executado
./programa_seq1
#FIM DO SCRIPT
para submeter o script sequencial_1, pode-se solicitar apenas uma máquina, e um único processador.
qsub -l nodes=1:ppn=1 sequencial_1
supondo que essa submissão ganhou um id 128, quando o PBS terminar a execução do job 128, ele vai gerar 2 arquivos:
sequencial_1.o128
esse arquivo é a saida que o script “sequencial_1” e o programa “programa_seq1” gerariam na tela
sequencial_1.e128
Esse arquivo possui os erros gerados durante a execução do script, caso existam erros.
Exemplo 2
Um script que submete um programa comum sequencial chamado “programa_seq2” e que esta na pasta “meus_programas”. O programa programa_seq2 aceita um parâmetro hipotético n. O script sequencial_2 vai executar 4 instâncias em alguma máquina do cluster. Para que as instâncias executem simultaneamente, é interessante solicitar uma cpu da máquina para cada instância:
Conteúdo do arquivo de script sequencial_2:
#Isso e um comentario, INICIO DO SCRIPT
#o script precisa entrar na pasta onde o programa esta
cd meus_programas
#agora a primeira instancia sera executada com n=100
#para que a o script nao fique bloqueado esperando a instancia
#terminar antes de chamar a seguinte, o comando e executado em
#background com o caracter & no fim do comando
./programa_seq2 -n 100 &
#simultaneamente, colocamos a segunda instancia para rodar
./programa_seq2 -n 1000 &
#agora a terceira instancia
./programa_seq2 -n 1050 &
#e finalmente a ultima
./programa_seq2 -n 1730 &
#e preciso fazer o script esperar pelo termino de todas as instancias com o comando
#wait. Se o script terminar e deixar alguma instancia rodando em background
#para tras o PBS pode matar a instancia antes dela terminar.
wait
#FIM DO SCRIPT
para submeter o script sequencial_2, pode-se solicitar apenas uma máquina, Para tirar proveito do possibilidade de rodar as instancias simultaneamente, é interessante solicitar quatro cpus, uma para cada instância.
qsub -l nodes=1:ppn=4 sequencial_2
Exemplo 3
Um script que submete um programa que tem a capacidade de rodar em paralelo em uma maquina, usando threads. Nesse caso, quanto mais cpus disponiveis na máquina maior a possibilidade de executar as threads do programa de forma realmente paralela. Um exemplo, são os programas que usam a biblioteca openmp para o trabalho feito em loops em threads.
O programa chama-se programa_thread1. Ele fica na pasta meus_programas
Conteúdo do arquivo de script thread_1:
#Isso e um comentário, INICIO DO SCRIPT
#o script precisa entrar na pasta onde o programa esta
cd meus_programas
#agora o programa_thread1 sera posto para executar. Como é um programa
#que pode se quebrar em threads, um numero maior de cpus disponíveis pode
#beneficiar o tempo de execução do programa
./programa_thread1
#FIM DO SCRIPT
para submeter o script thread_1, tirando proveito de sua característica multi-thread, é interessante solicitar tantas cpus quanto o programa e capaz de usar com proveito. Supondo que o programa consiga executar bem com as 8 cpus de uma máquina:
qsub -l nodes=1:ppn=8 thread_1
Exemplo 4
Como uma única máquina livre é capaz de fornecer até 8 cpus, o PBS pode colocar mais de um processo mpi em uma mesma máquina, pois é possível encaixar até 8 processos mpi em uma única máquina livre.
O programa chama-se programa_mpi1. Ele fica na pasta meus_programas
Conteúdo do arquivo de script mpi_1:
#Isso e um comentario, INICIO DO SCRIPT
#o script precisa entrar na pasta onde o programa esta
cd meus_programas
#agora o ambiente do mpi precisa ser iniciado. O arquivo de maquinas
#e criado dinamicamente pelo mpi, e seu caminho fica guardado na variavel
#chamada $PBS_NODEFILE.
#para verificar no arquivo de saida como o arquivo de maquinas ficou, podemos
#dar cat no arquivo de maquina
cat $PBS_NODEFILE
# O numero de maquinas que o PBS forneceu pode ser obtido pela contagem do
#numero de linhas (sem repeticao) do arquivo $PBS_NODEFILE
NUMERO_DE_MAQUINAS=`sort $PBS_NODEFILE | uniq | wc -l`
#para verificar que o numero de maquinas esta correto, em relacao ao arquivo de maquinas
cat $NUMERO_DE_MAQUINAS
#agora, iniciar o ambiente do mpi, com o comando mpdboot
mpdboot -n $NUMERO_DE_MAQUINAS -f $PBS_NODEFILE
#e possivel determinar o numero de processos, pelo numero de entradas no arquivo de maquinas
NUMERO_DE_PROCESSOS=`wc -l $PBS_NODEFILE`
#verificar no arquivo de saida, se o numero de processos era o esperado
cat $NUMERO_DE_PROCESSOS
#executar o programa mpi
mpiexec -n $NUMERO_DE_PROCESSOS programa_mpi1
#por ultimo, finalizar o ambiente mpi
mpdallexit
#FIM DO SCRIPT
como cada processo mpi desse exemplo requer apenas 1 processador uma maneira de fazer uma requisicao, e pedir 16 maquinas, sendo que cada uma deve ter uma cpu disponível.
qsub -l nodes=16:ppn=1 mpi_1
Lembrando que como uma única máquina pode ter ate 8 cpus livres, é possivel que uma só máquina seja reutilizada na requisição, e o arquivo de máquinas possuir mais de uma repetição da mesma máquina.
Uma outra maneira de executar esse programa mpi (uma maneira menos flexivel que a primeira), seria pedir 2 máquinas com 8 cpus livres:
qsub -l nodes=2:ppn=8 mpi_1