El juego
mytoy.cu es un sencillo programa CUDA que permite cambiar una variedad de rasgos en la capa software con objeto de evaluar de forma inmediata su influencia sobre el rendimiento de la GPU en la capa hardware.
El kernel computa operaciones en paralelo sobre cada uno de los elementos no nulos de una matriz dispersa. Es el programa irregular más sencillo que uno puede escribir, permitiendo explotar fácilmente las nuevas prestaciones con las que están dotadas las plataformas Kepler (como los multiprocesadores SMX o el Hyper-Q), junto con algunos otros mecanismos ya populares en CUDA prácticamente desde sus inicios. Como programador CUDA, acepta el reto de elegir la combinación óptima de parámetros que conducen a un rendimiento máximo. Y lo que es más importante aún, despliega el paralelismo de la manera más efectiva sobre los miles de cores de que dispone la GPU. De tus habilidades como programador CUDA, el conocimiento de su arquitectura, y la relación entre programa y circuitería, dependerá el éxito de tu empresa. Te recomendamos que asumas el reto como una escalera a subir peldaño a peldaño, acometiendo sucesivamente niveles de complejidad creciente según vayas ganando confianza a medida que alcanzas metas intermedias. Podemos vislumbrar, en general, tres niveles de dificultad:
- Básico: Jugar con los warps, los hilos y los bloques.
- Intermedio: Cambiar los lanzamientos de los kernels.
- Avanzado: Clasificar los kernels dentro de múltiples streams, asignando cada kernel al stream más adecuado.
Los puntos de interés del código mytoy.cu que permiten jugar con todos estos elementos están marcados con la etiqueta “MU” seguida de un número, cuyo significado es el siguiente:
Marca | Descripción | Variantes | Lo que estudiamos |
---|---|---|---|
MU1 |
Selecciona el tipo de dato |
int/float/double (inicialmente: double) |
El rendimiento de las ALU (aritmética entera) y FPU (aritmética de punto flotante) |
MU2 |
Selecciona el tipo de operación |
add/mul/div (inicialmente: add) |
La latencia de las operaciones aritméticas |
MU3 |
Calcula el número de bloques y su tamaño |
Bloques de 32, 64, 128, 192, 256, 384, 512, 768 y 1024 hilos (inicialmente: 1024) |
Cómo desplegar el máximo paralelismo |
MU4 | Declara los streams |
Un stream para cada kernel (elección inicial) o todos los kernels en un mismo stream. También se pueden elaborar soluciones intermedias con un conjunto de streams, cada uno agrupando a unos pocos kernels |
Cómo desplegar el máximo paralelismo |
MU5 |
Lanza los kernels agrupados en streams |
Mismas variantes que en MU4 |
Cómo desplegar el máximo paralelismo |
Argumento | Significado | Comentarios |
---|---|---|
Primero |
El número de GPU correspondiente al hardware en el que ejecutamos el código |
Habitualmente 0 (si el servidor tiene una sola GPU, es la opción por defecto) |
Segundo |
El número de operaciones realizadas sobre cada elemento de la matriz de entrada |
Afecta a la intensidad operacional. Útil para obtener todas las coordenadas que nos permiten dibujar la gráfica del modelo roofline para la GPU empleada |
Tercero |
El nombre del fichero que contiene la matriz dispersa con la que computamos (y que se encuentra en el directorio sparsematrices) |
sparsematrices/samplematrix.rua es la matriz de ejemplo (que podemos usar durante las pruebas preliminares) |
Cuarto |
El nombre del fichero en el que escribir los resultados obtenidos por el programa |
Útil si queremos inspeccionar los resultados finales para su validación |
Un ejemplo de comando que ejecuta el programa desde el shell del Linux sería (texto en negrita y azul):
/home/ujaldon> ./mytoy 0 4 sparsematrices/samplematrix.rua myoutputfile.txt