CUDA: MODELO DE PROGRAMACIÓN

Anuncio
CUDA:
MODELO DE PROGRAMACIÓN
Autor: Andrés Rondán
Tema: GPUGP: nvidia
CUDA.
Introducción
En Noviembre de 2006, NVIDIA crea CUDA, una
arquitectura de procesamiento paralelo de
propósito general, con un nuevo modelo de
programación paralela.
Compute Unified Device Architecture
Pequeña curva de aprendizaje.
Escalable a 100s cores y a 1000s hilos
paralelos.
Empezó como una pequeña extensión de C,
pero ya es soportada por OpenCL, Fortran...
Introducción
DEFINICIONES
En el ámbito CUDA:
Device = GPU
Host = CPU
Kernel = Función llamada desde el Host que se ejecuta
en Device
Array de hilos paralelos:
1 CUDA Kernel se ejecuta mediante un array de Threads.
Todos los Threads ejecutan el mismo código.
Cada Thread tiene un ID que se usa para direccionar la
memoria y tomar las decisiones de control.
Jerarquía
de hilos
Unidad básica de operación es el thread.
Los hilos están organizados en bloques de
threads.(Blocks)
Los bloques están organizados en mallas de
bloques. (Grids).
Un Grid solo puede ejecutar un Kernel.
Jerarquía
de hilos (II)
Jerarquía
de hilos (y III)
Hilos identificados mediante threadIdx: vector de
elementos 3D ( tiene 3 componentes, x, y y z) . Cada
hilo puede venir identificado por un índice 1, 2 ó 3
dimensiones.
Los hilos de un bloque pueden cooperar entre sí
mediante el uso de memoria compartida dentro del
bloque y sincronizando su ejecución para coordinar
los accesos a memoria.
Los grids pueden ser de 1 o 2 dimensiones, luego cada
block dentro de un grid puede ser direccionado por un
índice de 1 o 2 dimensiones mediante blockIdx.
Asimismo, la dimensión del bloque también se puede
obtener desde dentro del kernel mediante blockDim.
Jerarquía de
memoria
Cuda threads pueden acceder a los datos de
múltiples espacios de memoria durante su
ejecución.
Cada thread posee su propia memoria local.
Cada block su propia memoria compartida por todos
los threads del bloque y con el mismo tiempo de
vida que los threads que lo componen.
Todos los hilos tienen acceso a la memoria global.
Existen además otros 2 espacios de memoria
adicionales de sólo lectura: constant y texture
memory.
Jerarqía
de memoria
Modelo Hardware
Cooperación
CPU - GPU
El modelo de programación de CUDA asume que
los CUDA threads se ejecutan en un device
que actúa como coprocesador de un host que
ejecuta un programa.
También asume que host y device poseen su
propia DRAM, host memory y device memory.
Cuda proporciona instrucciones para reservar,
liberar, copiar memoria en la memoria del
device, así como transferir datos entre el host y
el device.
CUDA:
EXTENSIÓN DE C.
Kernel
// Kernel definition
__global__ void VecAdd(float* A, float* B, float* C)
{
...
Se define un kernel con la
}
Primitiva __global__.
int main()
Debe devolver void.
{
…
// Kernel invocation
VecAdd<<<1, N>>>(A, B, C);
}
Al invocarlo se le indica
<<tamaño grid, tamaño bloque>>
Escalabilidad
Cada hilo realiza la operación
Los índices del elemento de la matriz
correspondiente. En este caso, es
que se va a procesar se definirán pues
posible que el número de threads supere
en función del tamaño del bloque,
al número de elementos: controlar
del id el hilo dentro del bloque actual
y del tamaño del id del bloque actual.
// Kernel definition
__global__ void MatAdd(float A[N][N], float B[N][N],float C[N][N])
{
int i = blockIdx.x * blockDim.x + threadIdx.x;
int j = blockIdx.y * blockDim.y + threadIdx.y;
if (i < N && j < N)
C[i][j] = A[i][j] + B[i][j];
Se define la dimensión del
}
Bloque. Puede ser de 1 o 2 dimensiones.
int main()
Le estamos diciendo que cada bloque
{
Va a tener 16x16=256 threads
...
// Kernel invocation
dim3 dimBlock(16, 16);
dim3 dimGrid((N + dimBlock.x – 1) / dimBlock.x,(N + dimBlock.y – 1) /
dimBlock.y);
Se define la dimensión del
MatAdd<<<dimGrid, dimBlock>>>(A, B, C); Grid. También puede ser de 1 o 2
}
y depende del tamaño del bloque
y del tamaño del array.
Escalabilidad (II)
El tamaño del block es elegido aparentemente de
forma “arbitraria”, y el grid es creado con suficientes
blocks para tener un thread por un elemento de la
matriz.
Todos los Threads de un block se ejecutan dentro del
mismo core. El número de threads por block está
limitado por los recursos de memoria del core:
En la misma GPU, actualmente un block puede
contener 512 threads.
Escalabilidad (y III)
El tamaño de los datos suele ser más grande que
el de los hilos:
Independencia de ejecución entre bloques:
debe dar igual el orden, y si se ejecutan en
paralelo o en serie. Si no: __syncthreads().
Blocks necearios para permitir la escalabilidad
a diferentes números de core
Memoria
CUDA asume que device y host tienen su propia
memoria. En principio, device trabaja con la host
memory. Para que trabaje con su propia memoria,
CUDA proporciona, entre otros:
cudaMalloc(void **, size_t);
cudaMemcpy(void *,void *,
size_t,cudaMemcpyHostToDevice|
cudaMemcpyDeviceToHost);
cudaFree(void *);
COMPILACIÓN
Tenemos código que se va a ejecutar
en el host y código que se va a ejecutar
en el device.
Nvcc se va a encargar de separarlos.
Una vez separados, el código del host
se compilará con su compilador
habitual, pej. Cc, y el código del
device lo transformará en código
binario (cubin) o ensamblador (PTX)
Por último, para cargarlo y
ejecutarlo en el device la aplicación
se ayuda de las APIS proporcinadas
por los drivers de CUDA
Apéndice
Interoperatividad con Directx y OpenGL.
Versión 2.3.1 (26/08/2009)
Muy extendido: Resultados google del orden de
1 M en “nvidia cuda” y de 1 K en “nvidia cuda
programming guide”.
Arquitectura actual: nvidia FERMI: 512 cuda
cores.
228 universidades enseñan cuda actualmente. (4
de ellas Españolas)
Documentación
http://www.nvidia.com/object/cuda_home.html#
http://es.wikipedia.org/wiki/CUDA
Descargar