torque tutorial
TORQUE Resource manager es un software que permite «agendar» tareas computacionales,i.e.«tareas batch». Provee control sobre estas tareas y los recursos computacinoales de sistemas distribuidos. Posee los siguientes componentes:
Servidor: En este caso se llama pbs_server. Permite operaciones básicas como crear, modificar, borrar y ejecutar un trabajo.
Ejecutor: Es un demonio, llamado en nuestro caso pbs_mom, que pone el comando en ejecución cuando recibe una copia del trabajo de el server.
Agendador: Otro demonio que tiene las políticas para decidir que trabajo se ejecuta, donde y cuando. Usamos el agendador MAUI el cual se puede comunicar con varios MOMs para comunicar al servidor el estado de los recursos y para conocer del servidor el estado de los trabajos a ejecutar.
Hola Torque
Usted puede solicitar a TORQUE el estado de un nodo con el comando pbsnodes o de todos los nodos con pbsnodes -a, con los cuales debe obtener una salida como esta para cada nodo en el sistema:
wn1 state = free np = 32 ntype = cluster status = rectime=1376977699,varattr=,jobs=,state=free,netload=28936987148,gres=, loadave=1.04,ncpus=32,physmem=57801956kb,availmem=100795756kb, totmem=106629856kb,idletime=1149356,nusers=1,nsessions=2,sessions=2996358788, uname=Linux gfif-wn1 3.2.0-4-amd64 #1 SMP Debian 3.2.41-2 x86_64,opsys=linux
«free» significa que el nodo está en capacidad de correr tareas, «np» es el número de procesadores.
Enviar un trabajo
Para enviar un trabajo o tarea al sistema TORQUE es necesario crear un script de shell (puede ser bash, sh, ksh, etc) con directivas especiales a modo de comentario...#! /bin/sh #PBS -N prueba #PBS -o prueba.out #PBS -e prueba.err #PBS -l walltime=00:01:00 date hostname sleep 20 date
Archivo que hemos llamado prueba.sh para correrlo así
$ qsub prueba.sh
¿Cómo espera usted que sea la salida de este trabajo?
Si está corriendo en múltiples máquinas ¿Dónde se espera encontrar el stdout?
Monitorear el trabajo
El comando qstat -a nos muestra el estado de los trabajos de todas las colas, obtenemos uua salida como estaJob ID Username Queue Jobname SessID NDS TSK Memory Time S Time -------------------- -------- -------- ---------------- ------ ----- --- ------ ----- - ----- 1171.gfif.udea.e gerardo batch prueba 21476 2 2 -- 00:01 R --
El commando
$ pbsnodes -a
wn4 state = free np = 72 ntype = cluster jobs = 0/8530.gfifmaster, 1/8530.gfifmaster, 2/8530.gfifmaster status = ...
Que quiere decir que nodo `wn4` tiene procesadores disponible ( status=free ) pues de los 72 se están usando 3 (`jobs = 0/8530.gfifmaster, 1/8530.gfifmaster, 2/8530.gfifmaster`)
Algunos comandos de pbs para monitoreo y control son
qstat -a | Verifica el estado de los trabajos, las colas y el servidor PBS. |
qstat -f | Obtiene toda la información del trabajo lanzado, como: Recursos pedidos, cola, fuente, destino, propietario, recursos límite, etc. |
qdel job.ID | Borra un trabajo. |
qhold job.ID | Pone un trabajo en estado de espera si se encuentra en cola. |
qrls job.ID | Saca a un trabajo del estado de espera. |
Algunos comandos útiles de maui
showq | Muestra una lista detallada de los trabajos lanzados. |
showbf | uestra los recursos libres. |
checkjob job.ID | muestra una descripción detallada del trabajo. |
showstart job.ID | Muestra el tiempo estimado de comienzo del trabajo. |
El script de PBS
Algunas opciones de PBS para el script sonOpción | Descripción |
#PBS -N myJob | Asigna el nombre a un trabajo |
#PBS -l nodes=4:ppn=2 | El número de nodos y procesos por nodo |
#PBS -q queuename | Asigna la cola en al que su trabajo va a estar. |
#PBS -l walltime=01:00:00 | El tiempo de reloj «de pared» durante el cual su trabajo puede correr. |
#PBS -o mypath/my.out | La dirección y el nombre del archivo para guardar el stdout. |
#PBS -e mypath/my.err | La dirección y el nombre del archivo para guardar el stderr. |
#PBS -j oe | Une el stdout con el stderr. |
#PBS -M user@mail | email del usuario al cual enviar reportes. |
#PBS -m b | Envia un email cuando el trabajo comienza. |
#PBS -m e | Envia un email cuando el trabajo termina. |
#PBS -m a | Envia un email cuando el trabajo aborta por un error. |
#PBS -V | Exporta todas las variables de entorno al trabajo. |
Algunas variables de entorno de PBS son
PBS_O_HOME | La ruta al home de el que se corrió qsub. |
PBS_O_WORKDIR | El directorio en el que se corrió qsub. |
PBS_O_LOGNAME | El nombre de usuario que corrió qsub. |
PBS_O_HOST | El nombre de la máquina en la que se corrió qsub. |
PBS_O_QUEUE | La cola a la que el trabajo fue enviado. |
PBS_JOBID | El identificador que asigna PBS al trabajo. |
PBS_JOBNAME | El nombre del trabajo. |
PBS_NODEFILE | El archivo que contiene la lista de nodos para tareas en paralelo. |
El proceso de los procesos.
Multiples trabajos
En este ejemplo vamos a ver como podemos acondicionar nuestros programas o nuestro codigo para que trabaje en simultaneo de acuerdo a los argumentos.creemos una carpeta para hacer el siguente ejercicio.
Creemos un arhcivos integral.cpp
#include<stdio.h> #include<stdlib.h> #include<math.h> double integral(double (*fun)(double),double min,double max, double delta=0.1) { double sum=0; double i; for(i=min;i<max;i+=delta) sum+=fun(i)*delta; return sum; } int main(int argc,char *argv[]) { if(argc!=3) { printf("Error: requiere 2 argumentos, 1=total procesos 2=proceso actual.\n"); return -1; } int total_procs=atoi(argv[1]); int actual_proc=atoi(argv[2]); double min=0; double max=2*M_PI; double parte=(max-min)/total_procs; double pmin=min+(actual_proc)*parte; double pmax=pmin+parte; printf("int(sin,%lf,%lf)=%lf\n",pmin,pmax,integral(sin,pmin,pmax)); return 0; }
Compilar con:
g++ -o integral integral.cc
creamos el archivo job.sh que contiene las indicaciones para qsub
#!/bin/bash # # #PBS -N JODID #PBS -M omazapa@gfif.udea.edu.co #PBS -t 0-4 #echo jobid=$PBS_ARRAYID $PBS_O_WORKDIR/integral 5 $PBS_ARRAYID
Corremos el script, el status E(Exit) indica que finaliza inmediatamente.
[omazapa] [gfif] [~/pbs/jobid]$ qsub job.sh 1189.gfif.udea.edu.co [omazapa] [gfif] [~/pbs/jobid]$ qstat Job id Name User Time Use S Queue ------------------------- ---------------- --------------- -------- - ----- 1189-0.gfif JODID-0 omazapa 00:00:00 E batch 1189-1.gfif JODID-1 omazapa 00:00:00 E batch 1189-2.gfif JODID-2 omazapa 00:00:00 E batch 1189-3.gfif JODID-3 omazapa 00:00:00 E batch 1189-4.gfif JODID-4 omazapa 00:00:00 E batch
El resultado de nuestro problema esta en los acrhivos que genera y tenemos que obtenerlo.
[omazapa] [gfif] [~/pbs/jobid]$ cat JODID.o1189-* int(sin,0.000000,1.256637)=0.683713 int(sin,1.256637,2.513274)=1.161746 int(sin,2.513274,3.769911)=0.034286 int(sin,3.769911,5.026548)=-1.140556 int(sin,5.026548,6.283185)=-0.739188
para obtenerlo corremos el siguiente comando.
cat JODID.o* | gawk -F"=" '{sum+=$2} END {printf("%f\n" ,sum)}' [omazapa] [gfif] [~/pbs/jobid]$ cat JODID.o* | gawk -F"=" '{sum+=$2} END {printf("%f\n" ,sum)}' 0.000001
Message Passing Interface (MPI)
En esta parte vamos a ver como correr programar paralelizados con mpi, para nuetro caso compilaremos con openmpi.#include <stdio.h> #include <mpi.h> int main (int argc, char *argv[]){ int rank, size; char hostname[256]; MPI_Init (&argc, &argv); /* starts MPI */ MPI_Comm_rank (MPI_COMM_WORLD, &rank); /* get current process id */ MPI_Comm_size (MPI_COMM_WORLD, &size); /* get number of processes */ gethostname(hostname,255); printf( "Hello world from %s process %d of %d\n", hostname,rank, size ); MPI_Finalize(); return 0; }
Bueno el código lo compilamos con
CC=mpicc make hello
el script para el job llamemolo mpi.sh
#!/bin/sh ### Job name #PBS -N hellompi ### Output files #PBS -e hellompi.err #PBS -o hellompi.log ### Mail to user #PBS -M omazapa@gfif.udea.edu.co ### Queue name (small, medium, long, verylong) batch is default queue #PBS -q batch ### Number of nodes and ppn (proc per node) #PBS -l nodes=2:ppn=5 # This job's working directory mpirun -machinefile $PBS_NODEFILE -np 10 $PBS_O_WORKDIR/hello
Mpi python
Para python tenemos lo siguiente hello.pyfrom mpi4py import MPI import sys size = MPI.COMM_WORLD.Get_size() rank = MPI.COMM_WORLD.Get_rank() name = MPI.Get_processor_name() sys.stdout.write("Helloworld! I am process %d of %d on %s.\n" % (rank, size, name))
y el script para el job seria
#!/bin/sh ### Job name #PBS -N hellompi ### Output files #PBS -e hellompi.err #PBS -o hellompi.log ### Mail to user #PBS -M omazapa@gfif.udea.edu.co ### Queue name (small, medium, long, verylong) batch is default queue #PBS -q batch ### Number of nodes and ppn (proc per node) #PBS -l nodes=2:ppn=5 # This job's working directory mpirun -machinefile $PBS_NODEFILE -np 10 python $PBS_O_WORKDIR/hello.py
Ejercicios
busqueda.tar.gz
En el archivo busqueda.tgz hay 2 programas(uno en C y otro en python) y 3 archivos con números del 0 al 9. La idea detrás de cada programa es contar las ocurrencias de alguno de estos números en los 3 archivos.
Se debe realizar en primera instancia el script de PBS que envie este solo proceso donde hayan recursos disponibles.
Luego se debe modificar el programa y el script de tal manera que haga la búsqueda en 3 procesos diferentes.
Referencias
torque jobs
Ejemplos
Random output
[+]Sistema de colas
- Cola corta por defecto: 24h, sin restricciones (5 nodos)
- Cola larga 720h: tiene 3 nodos con máximo 72 cores.
- PBS -q long
Matar múltiples trabajos
qdel $(qstat | awk '{print $1}' | grep -E '^[0-9]')
Muchas gracias
Diego