A GINA usa o gerenciador de filas TORQUE, mantendo duas filas:
Processos devem ser submetidos à fila route, que os encaminha à mais apropriada das duas acima.
A situação das filas pode ser consultada com qstat
; qstat -q
mostra a situação de todas as filas:
penteado@gina:~> qstat -q server: gina-n2-ib Queue Memory CPU Time Walltime Node Run Que Lm State ---------------- ------ -------- -------- ---- --- --- -- ----- batch -- -- -- -- 0 0 -- D S route -- -- -- -- 0 0 -- E R short -- -- 01:00:00 -- 0 0 20 E R long -- -- 48:00:00 -- 0 0 10 E R ----- ----- 0 0
Os processos do usuário podem ser consultados com apenas qstat
:
penteado@gina:~/subtest> qstat Job id Name User Time Use S Queue ------------------------- ---------------- --------------- -------- - ----- 15.gina ExampleJob penteado 0 R short 16.gina ExampleJob penteado 0 R short
Ou, para muito mais detalhes, qstat -f
.
A submissão de processos é feita com qsub
. Ela pode ser feita especificando todas as opções diretamente com argumentos para qsub
, ou (o mais comum), criando-se um script que especifica os argumentos como comentários. Por exemplo, criando o script example_job.sh
:
#!/bin/sh # #This is an example script example_job.sh #To be used with TORQUE's qsub ("qsub example_job.sh"), not directly # #These commands set up the Grid Environment for your job: #PBS -N example_job #PBS -d /home/some_user/some_place/ #PBS -l procs=3,walltime=00:01:00 #PBS -q route #PBS -M some_user #PBS -m abe #print the time and date echo "Starting TORQUE script $PBS_JOBNAME at" date #print the name of the node executing these lines (it is only one node) uname -a #print some more data from TORQUE echo "PBS_NODEFILE: $PBS_NODEFILE" cat $PBS_NODEFILE echo "PBS_GPUFILE: $PBS_GPUFILE" if [ -e $PBS_GPUFILE ] then cat $PBS_GPUFILE fi #go to the proper directory cd $PBS_O_WORKDIR #this is where something useful would usually be done #print the time and date again echo "Ending TORQUE job $PBS_JOBID at " date
As linhas comentadas com #PBS
especificam argumentos para o qsub
. Veja o seu manual (man qsub
), ou a sua documentação online para mais detalhes. No caso, estão sendo especificados:
-N example_job
).-d /home/some_user/some_place/
).-l procs=3,walltime=00:01:00
).-q route
).-M some_user
).-m abe
).Se for usar o arquivo acima, edite pelo menos o endereço de email usado, que é para onde será mandado um email informado quando o trabalho for concluído, e o diretório usado para execução.
Trabalhos que usem mais de um núcleo devem o solicitar em uma de três formas:
procs
. Ex: #PBS -l procs=4,walltime=00:01:00
nodes
, para quaisquer nós. Ex: #PBS -l nodes=2:ppn=4,walltime=00:01:00
(2 nós, 4 processos por nó).nodes
, para um nó específico. Ex: #PBS -l nodes=gina-n1-ib:ppn=4,walltime=00:01:00
(só o nó gina-n1, 4 processos por nó).
A escolha de um ou outro nó é mais relevante com relação ao local onde estarão os arquivos a serem acessados pelo programa. O diretório /home reside no nó gina-n2, sendo exportado por nfs para o nó gina-n1. Portanto, o acesso a arquivos no /home é mais lento do nó gina-n1, pois se dá pela rede (ethernet). Os nomes dos nós para solicitação nas filas são gina-n1-ib
e gina-n2-ib
.
Caso seja necessário o programa lidar com arquivos localmente (por eficiência de acesso, ou para exceder a quota de usuário (10 GB)), pode ser usado o /tmp
. Neste caso, todos os arquivos do usuário devem residir dentro de um diretório com o nome do usuário, no /tmp
(ex: /tmp/some_user/
).
Para transferência entre nós, e para tornar links mais convenientes, ambos os nós vêem os diretórios /tmp_gina-n1
e /tmp_gina-n2
, correspondendo ao /tmp
de cada nó.
Trabalhos que usem GPUs devem o solicitar. Apenas as duas GPUs do nó gina-n1 estão disponíveis para as filas (as duas do nó gina-n2 estão reservadas para uso interativo, sem a fila). Exemplo:
#PBS -l nodes=1:ppn=1:gpus=1,walltime=01:00:00
Programas com uso de MPI devem ser chamados com o mpirun, com os argumentos determinados pelo TORQUE. Ex:
#!/bin/sh # #This is an example script example_MPI.sh #To be used with TORQUE's qsub ("example_MPI.sh"), not directly # #These commands set up the Grid Environment for your job: #PBS -N example_MPI #PBS -d /home/some_user/some_place/ #PBS -l nodes=1:ppn=3,walltime=00:01:00 #PBS -q route #PBS -M some_user #PBS -m abe #print the time and date echo "Starting TORQUE script $PBS_JOBNAME at" date #print the name of the node executing these lines (it is only one node) uname -a #print some more data from TORQUE echo "PBS_NODEFILE: $PBS_NODEFILE" cat $PBS_NODEFILE echo "PBS_GPUFILE: $PBS_GPUFILE" if [ -e $PBS_GPUFILE ] then cat $PBS_GPUFILE fi #determine the number and name of processors that TORQUE has allocated np=`wc -l $PBS_NODEFILE` np=${np%"$PBS_NODEFILE"} echo "Running $np processes" map=`tr '\n' ':' <$PBS_NODEFILE` #call an example MPI program, with the proper mpirun arguments mpirun -machinefile $PBS_NODEFILE -map $map -np $np $PBS_O_WORKDIR/mpitest.out #print the time and date again echo "Ending TORQUE job $PBS_JOBID at " date
Um programa de teste para verificar a execução por MPI pode ser
program main use mpi implicit none integer :: numtasks,i integer :: name_len,name_len_max !Variables for MPI integer :: isendbuf,isendcount,ierr,rank,root,rc character(len=MPI_MAX_PROCESSOR_NAME) :: proc_name integer,allocatable :: irecvbuf(:) character(1),allocatable :: crecvbuf(:) !Variables for the arrays to use to waste some time integer,parameter :: length=100000 real(selected_real_kind(15,307)) :: atmp(length),btmp(length) !MPI initialization call mpi_init(ierr) if (ierr .ne. MPI_SUCCESS) then print *,'Error starting MPI program. Terminating.' call mpi_abort(MPI_COMM_WORLD,rc,ierr) end if !Initialize "global" variables root=0 !The process that will do the receiving and output isendcount=1 !How many integerss will be gathered !Get the MPI "locals" call mpi_comm_rank(MPI_COMM_WORLD,rank,ierr) !The process rank call mpi_get_processor_name(proc_name,name_len,ierr) !The processor name !Do the initialization, only by the root process if (rank .eq. root) then call mpi_comm_size(MPI_COMM_WORLD,numtasks,ierr) allocate(irecvbuf(numtasks*isendcount)) !Make room for gathering the process ranks endif !Do the work (by all processes) isendbuf=rank !Find out the maximum length of the processor name, accross all processes call mpi_allreduce(name_len,name_len_max,isendcount,MPI_INTEGER,MPI_MAX,MPI_COMM_WORLD,ierr) !Make room to get the processor names (has to be here, after knowing the maximum processor name length) if (rank .eq. root) then allocate(crecvbuf(name_len_max*numtasks)) endif !Waste some time, so that the processes take some noticeable time to run forall(i=1:length) atmp(i)=(i-1)/((length-1)*1d0) do i=0,100 btmp=acos(cos(atmp*acos(-1d0))) enddo !Get the results from everybody (ranks and names) call mpi_gather(isendbuf,isendcount,MPI_INTEGER,irecvbuf,isendcount,MPI_INTEGER,root,MPI_COMM_WORLD,ierr) call mpi_gather(proc_name(1:name_len_max),name_len_max,MPI_CHARACTER,crecvbuf,name_len_max,MPI_CHARACTER,root,MPI_COMM_WORLD,ierr) !Show the results if (rank .eq. root) then print *,'I am process number ',rank print *,'Running on processor ',proc_name(1:name_len) print *,'Number of tasks is ',numtasks do i=0,numtasks-1 print *,'Process rank ',irecvbuf(i+1),' ran on processor ',crecvbuf(i*name_len_max+1:(i+1)*name_len_max) enddo endif call mpi_finalize(ierr) end program main
Que pode ser compilado com o compilador PGI com
mpif90 mpitest.f90 -o mpitest.out
Este programa, se executado por um script como o desta seção, resulta em algo como
Starting TORQUE script mpitest at Mon Apr 11 01:49:14 BRT 2011 Linux gina-n2 2.6.32.13-0.4-default #1 SMP 2010-06-15 12:47:25 +0200 x86_64 x86_64 x86_64 GNU/Linux PBS_NODEFILE: /var/spool/torque/aux//181.gina-n2-ib gina-n2-ib gina-n2-ib gina-n2-ib gina-n2-ib PBS_GPUFILE: /var/spool/torque/aux//181.gina-n2-ibgpu Running 4 processes I am process number 0 Running on processor gina-n2 Number of tasks is 4 Process rank 0 ran on processor gina-n2 Process rank 1 ran on processor gina-n2 Process rank 2 ran on processor gina-n2 Process rank 3 ran on processor gina-n2 Ending TORQUE job 181.gina-n2-ib at Mon Apr 11 01:49:21 BRT 2011
OpenMP exige memória compartilhada. Como não há memória compartilhada entre os dois nós, programas com OpenMP precisam ser executados em um único nó. Como exemplo, o script acima poderia ser:
#!/bin/sh # #This is an example script example_OMP.sh #To be used with TORQUE's qsub ("example_OMP.sh"), not directly # #These commands set up the Grid Environment for your job: #PBS -N example_OMP #PBS -d /home/some_user/some_place/ #PBS -l nodes=1:ppn=3,walltime=00:01:00 #PBS -q route #PBS -M some_user #PBS -m abe #print the time and date echo "Starting TORQUE script $PBS_JOBNAME at" date #print the name of the node executing these lines (it is only one node) uname -a #print some more data from TORQUE echo "PBS_NODEFILE: $PBS_NODEFILE" cat $PBS_NODEFILE echo "PBS_GPUFILE: $PBS_GPUFILE" if [ -e $PBS_GPUFILE ] then cat $PBS_GPUFILE fi #determine the number and name of cores that TORQUE has allocated np=`wc -l $PBS_NODEFILE` np=${np%"$PBS_NODEFILE"} echo "Running on $np cores" export NCPUS=$np #go to the proper directory cd $PBS_O_WORKDIR #this is where the OpenMP program would be called #print the time and date again echo "Ending TORQUE job $PBS_JOBID at " date
O script é executado então simplesmente passando-o como argumento ao qsub
: qsub /home/user/example.sh
. As saídas que o processo envia ao STDOUT
e STDERR
(normalmente conectador ao terminal) são redirecionadas para arquivos com nomes baseados no nome do trabalho e Job id
, como ExampleJob.o15
(STDOUT
para o trabalho 15) e ExampleJob.e15
(STDERR
para o trabalho 15). No caso do script acima, ele não gera erro (o arquivo do STDERR
fica vazio), e a saída do STDOUT
é algo do tipo:
Starting TORQUE script example_job at Mon Apr 11 01:49:14 BRT 2011 Linux gina-n2 2.6.32.13-0.4-default #1 SMP 2010-06-15 12:47:25 +0200 x86_64 x86_64 x86_64 GNU/Linux PBS_NODEFILE: /var/spool/torque/aux//181.gina-n2-ib gina-n2-ib gina-n2-ib gina-n2-ib gina-n2-ib PBS_GPUFILE: /var/spool/torque/aux//181.gina-n2-ibgpu Ending TORQUE job 181.gina-n2-ib at Mon Apr 11 01:49:21 BRT 2011
Trabalhos podem ser removidos da fila com qdel
, através do seu Job id
:
penteado@gina:~/subtest> qstat penteado@gina:~/subtest> qsub ./qtest.sh 18.gina.iag.usp.br penteado@gina:~/subtest> qstat Job id Name User Time Use S Queue ------------------------- ---------------- --------------- -------- - ----- 18.gina ExampleJob penteado 0 R short penteado@gina:~/subtest> qdel 18.gina penteado@gina:~/subtest> qstat Job id Name User Time Use S Queue ------------------------- ---------------- --------------- -------- - ----- 18.gina ExampleJob penteado 00:00:00 C short
Trabalhos completos (status C
) só continuam sendo mostrados na saída do qstat
por 5 dias após seu encerramento.