{% extends "base.html" %} {% block content %}

¿Qué es tablón?

Tablón es un sistema de ejecución de programas paralelos diseñado por los profesores de la asignatura de computación paralela :computer::computer::computer: para poder ejecutar códigos usando diferentes tecnologías paralelas y para crear rankings de las soluciones de los alumnos de las prácticas propuestas.

¿Cómo funciona?

Tablón se compone de tres elementos: un cliente para enviar las peticiones de ejecución, un servidor de aplicaciones que trata estas peticiones y un servidor web para ver los resultados.

Las colas

Cada tablón tiene una serie de colas de ejecución que se pueden ver desde el menú Queues del servidor web. Cada cola está pensada para ejecutar un tipo de programa: secuenciales, OpenMP, MPI o CUDA. Además cada cola tiene unas restricciones en cuanto al número de hilos, procesos y duración del programa que pueden ejecutar.

El cliente

El cliente es un script python cuyo enlace se encuentra en el menú de está página (Client). Es posible que se creen diferentes copias de tablón en varias máquinas, es necesario descargar el cliente para cada uno de los servidores. Para usarlo hay que disponer de Python 2. El cliente actual se ha probado con la versión 2.7.10 de python. El cliente se utiliza para enviar los fuentes de los programas a ejecutar en una de las colas del tablón.
Supongamos que queremos ejecutar el siguiente programa C (hello.c) en la cola sequential.
//C hello world example
#include <stdio.h>
int main(){
	printf("Hello world\n");
	return 0;
}

Para ejecutar este programa debemos descargar el cliente, darle permisos de ejecución (chmod) y ejecutarle con los siguientes parametros.
./client -u USUARIO [-x PASSWORD] -q sequential hello.c [PARAMETROS]

El nombre de usuario, la cola y el código fuente del programa son parámetros obligatorios. La contraseña se puede introducir como parámetro o sino el cliente te la pedirá. También se pueden enviar parámetros al programa. En las colas de OpenMP y MPI se puede además especificar el número de procesos o hilos.
-n PROCESOS -t HILOS

Si el envío es correcto, el servidor responderá con un mensaje similar al siguiente donde se encuenta la dirección web para ver los resultados del programa.
Conecting usuario@myserver.mydomain:8080
Successful authentication
Sending request
Request sent successfully
Request id 17
http://myserver.mydomain:8080/request?rid=17

Hilos OpenMP

Para escoger el número de hilos OpenMP, hay que especificar el parámetro -t del cliente. Por defecto el número de hilos es 1. En tablón, la función omp_set_num_threads ya no tiene prioridad. Aunque se puede seguir utilizando para reducir el número de hilos que se usa en la región paralela.

Por ejemplo, el siguiente código selecciona manualmente 3 hilos pero solo se hará efectivo cuando desde el cliente se envíe el programa con -t >= 3.

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[]) {

	int maxt = omp_get_max_threads();
	printf("Max threads is: %d\n", maxt);

	omp_set_num_threads(3);

	int tid, tnum;

	#pragma omp parallel private(tnum, tid)
	{
		tid = omp_get_thread_num();
		tnum = omp_get_num_threads();
		printf("Hello World from thread = %d/%d\n", tid, tnum);
	}

	return 0;
}

cputils.h

Los código enviados puede hacer uso de la librería cputils.h que tiene una serie de funciones de ayuda. Podéis bajarlos una versión de cputils.h para compilar en vuestras máquinas en aquí

Las funciones son:

{# #}
Función Descripción
double cp_Wtime() Devuelve el tiempo, similar a omp_get_wtime() o MPI_Wtime().
int cp_FileSize(char * name, size_t * size) Función que calcula el tamaño de un fichero. El parámetro name es la cadena con el nombre del fichero y size es un puntero donde se guarda su tamaño. La función devuelve 1 si la operación a tenido éxito o 0 en caso contrario.
int cp_FileRead(char * name, void * ptr) Función que lee el contenido de un fichero. El parámetro name es la cadena con el nombre del fichero y ptr es un puntero donde se guardará el contenido. El puntero debe hacer referencia a una zona de memoria válida reservada anteriormente. La función devuelve 1 si la operación a tenido éxito o 0 en caso contrario.

Leaderboards

Existen unas colas especiales, asociadas a las colas básicas que tienen un listado (leaderboard) con el ranking de los códigos de los alumnos para un cierto problema. Los programas se ordenan según su tiempo de proceso (más rápido mejor).

Cuando se envía a una de estas colas, el servidor tablón ignora el número de procesos e hilos, así como los argumentos de entrada. El servidor ejecuta varias veces los programas con unos parámetros prefijados, compara la solución ofrecida por el alumnos y si es correcta, añade una entrada en el listado correspondiente.

Por ejemplo, la cola sequential tiene asociado el leaderboard suma. Este leaderboard espera recibir un programa secuencial que debe sumar los valores enteros que se le pasan como argumentos.

Un programa válido para un leaderboard debe realizar la tarea que se le pide e imprimir por la salida estándar: una linea con el tiempo y otra linea por cada resultado que se pida. Un programa válido para el leaderboard suma es por ejemplo:

/*
* Program that sum integers
*/

#include <stdio.h>
#include <stdlib.h>
#include "cputils.h"

int main(int argc, char *argv[]){

	double start_time = cp_Wtime();

	int num = 0;
	int i;
	for(i=1; i<argc; i++){
		num += atoi(argv[i]);
	}

	double end_time = cp_Wtime();

	printf("Result: %d\n",num);
	printf("Time: %f\n",end_time-start_time);

	return EXIT_SUCCESS;
}

La salida para la entrada: 10 6 2, es:

Result: 18
Time: 0.000009

Tablón obtiene el tiempo de ejecución del programa, algún alumno puede sentirse tentado de hacer trampas (por ejemplo, dividiendo el tiempo por algún factor correctivo). Tablón almacena todos los códigos enviados, una vez que termine el concurso se comprobarán los resultados y se descalificará a todos los alumnos que empleen medios no lícitos para mejorar su posición en el ranking.

Compilador de tablón

Es aconsejable que los programas solo impriman por pantalla lo mínimo necesario ya que existe una limitación en el número de caracteres (ver sección siguiente) y porque puede ocurrir que el resultado no se considere cómo válido en el leaderboard.

Los programas que se compilan en tablón tienen definido el macro CP_TABLON, los mensajes de debug que se utilizan para las ejecuciones en local se pueden imprimir usando compilación condicional.

#if !defined( CP_TABLON )
	printf("Esto no se imprime en tablón\n");
#endif

Límites, quotas y restricciones

Para no sobrecargar el tablón, los usuarios tienen un límite de peticiones por minuto. Cada usuario tiene también un tiempo de computo máximo asignado en tablón (quota). Si se usa por completo la quota, el usuario aún podrá enviar programa pero tendrá como penalización un tiempo mayor entre envíos. Otra limitación el el tamaño del buffer de salida (stdout). El número máximo de caracteres que se pueden imprimir desde el programa y que luego aparecen en la página son 2000 caracteres. Si el usuario realiza más llamadas printf, el resto de la salida no será almacenado. Por seguridad, existen ciertas funciones que no se pueden invocar desde el código, fopen, system, etc. Toda la entrada/salida se debe realizar usando las funciones de la librería cputils.h o con la salida estándar.

Reinicios

El servidor tablón está configurado para reiniciarse cada cierto tiempo. De está forma se eliminan trabajos erróneos y se eliminan las peticiones http no completas. El tiempo hasta el próximo reinicio se muestra en la página principal. {#

Programación con CUDA: Gestión de la cache L1/shared memory

Nuevo cliente 1.6:

Kernels CUDA

Cuando se programa en CUDA es habitual separar el código de los kernels en un fichero diferente. El cliente lee y combina en un único fichero los incluye con extensión .cu cuyo nombre empieza por kernel. Por ejemplo:
// OK
#include "kernel.cu"
#include "kernel_XXX.cu"

#include "mikernel.cu" // No funciona

#}

Características de las máquinas

Incluir aquí la descripción de las máquinas disponibles.

Máquina CPU GPU
Ejemplo Xeon E5 (12 cores) @ 1.9Ghz 4 x GTX Titan Black 2880 @ 980 Mhz
{#

Cuando se envía un programa a una cola MPI, se reservan máquinas hasta que el número de cores sea igual o mayor al número de procesos MPI. Hasta 4 procesos se ejecutan todos en una misma máquina. Para más de 4 se necesitan varias. Por ejemplo, para 6 procesos se reservan 2 máquinas. El sistema de gestión de colas coloca los procesos en las máquinas reservadas. En el caso de 6 procesos, al reservar 2 máquinas, colocará 3 procesos en cada máquina.

Cuando se envía un trabajo MPI no es posible elegir la máquina en la que se ejecuta, sino que se ejecuta en las primeras máquinas que se encuentren libres. Es posible que dos ejecuciones con los mismos parámetros obtengan un tiempo diferente porque se estén ejecutando sitios diferentes.

#} {% endblock %}