Primeros pasos con CUDA -...

78
Primeros pasos con CUDA Clase 1

Transcript of Primeros pasos con CUDA -...

Page 1: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Primeros pasos con CUDA

Clase 1

Page 2: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Ejemplo: suma de vectores

● Comencemos con un ejemplo sencillo: suma de vectores.– Sean A, B y C vectores de dimensión N, la suma se define como:

– C = A + B donde Ci = Ai + Bi

– Esta operación suma cada elemento de A y B se almacena en C.

Page 3: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1

Page 4: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1

C

c0

+

=

Page 5: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1

C

c0 c1

+ +

=

Page 6: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1

C

c0 c1 c2

+ + +

=

Page 7: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1

C

c0 c1 c2 c3 cN-1

+ + + +

=

Page 8: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores solución I/*

Suma de vectores secuencial

*/

vector_ops.cu

/* Suma de vectores (inplace) */int vector_ops_suma_sec(float *v1, float *v2, int dim){ for (int i = 0; i < dim; i++) { v1[i] = v1[i] + v2[i]; }

return 1;}

vector_ops.cu

Page 9: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores solución I/*

Suma de vectores secuencial

*/

vector_ops.cu

/* Suma de vectores (inplace) */int vector_ops_suma_sec(float *v1, float *v2, int dim){ for (int i = 0; i < dim; i++) { v1[i] = v1[i] + v2[i]; }

return 1;}

Complejidad computacional lineal: O(N) donde N es la dimensión de los arreglos.

vector_ops.cu

Page 10: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores solución I

Tiene orden de complejidad lineal, al aumentar el número de elementos aumenta linealmente la cantidad de operaciones.

Page 11: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores solución I

Tiene orden de complejidad lineal, al aumentar el número de elementos aumenta linealmente la cantidad de operaciones.

Para vectores pequeños la solución es correcta.

Page 12: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores solución I

Tiene orden de complejidad lineal, al aumentar el número de elementos aumenta linealmente la cantidad de operaciones.

Para vectores pequeños la solución es correcta.

Para vectores muy grandes este tipo de solución puede ocasionar penalizaciones en el tiempo de cómputo.

Page 13: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

● ¿Cómo sería una solución paralela?

Se puede paralelizar la suma → el cálculo de cada elemento del vector resultante es independiente de los demás elementos del vector:

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1…

Page 14: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1…

Si en vez de un único procesador disponemos P procesadores, dividimos los cálculos entre los P procesadores.

● ¿Cómo sería una solución paralela?

Se puede paralelizar la suma → el cálculo de cada elemento del vector resultante es independiente de los demás elementos del vector:

Page 15: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1…

C

c0 c1 c2 c3 cN-1

=

Si contamos con N procesadores, realizamos todos los cálculos al mismo tiempo. + + + + + + +

● ¿Cómo sería una solución paralela?

Se puede paralelizar la suma, → el cálculo de cada elemento del vector resultante es independiente de los demás elementos del vector:

c0 c1 c2 c3 cN-1…

=

Page 16: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1…

C

c0 c1 c2 c3 cN-1…

Si contamos con N procesadores, realizamos todos los cálculos al mismo tiempo. + + + + + + +

De orden lineal a orden constante

● ¿Cómo sería una solución paralela?

Se puede paralelizar la suma, → el cálculo de cada elemento del vector resultante es independiente de los demás elementos del vector:

=

Y se resuelve en paralelo todos losresultados del vector.

Page 17: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Entonces...

Tengo una PC re linda...

Page 18: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Entonces...

Tengo una PC re linda...

Tengo una GPU que me dicen que es re linda...

Page 19: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Entonces...

Tengo una PC re linda...

Tengo una GPU que me dicen que es re linda...

Tengo dos vectores para sumar...

A

B…

Page 20: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Entonces...

Tengo una PC re linda...

Tengo una GPU que me dicen que es re linda...

Tengo dos vectores para sumar...

¿¿Cómo utilizo estas arquitecturas para solucionar

mi problema??

A

B…

Page 21: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

CUDA (Compute Unified Device Architecture)

En Noviembre de 2006 NVIDIA introduce CUDA que hace referencia tanto a un compilador como a un conjunto de

herramientas de desarrollo creadas por NVIDIA.

CUDA es una arquitectura de software y hardware que permite a GPUs ejecutar programas escritos en C, C++,

Fortran, DirectCompute y otros lenguajes.

Page 22: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

CUDA (Compute Unified Device Architecture)

Un programa CUDA es un programa híbrido: – Código secuencial → se ejecuta en CPU

– Código paralelo → se ejecuta en GPU

Page 23: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

CUDA (Compute Unified Device Architecture)

Un programa CUDA es un programa híbrido: – Código secuencial → se ejecuta en CPU

– Código paralelo → se ejecuta en GPU

Código secuencialInicializaciones

Lectura de datos de entrada

Código paralelo

Código secuencialMuestra de resultados

Almacenamiento de resultados

….

….

Modelo SIMD - STMD

Page 24: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

CUDA ● Cómo es la parte paralela de la aplicación?

● Un programa CUDA invoca a funciones paralelas

llamadas kernels. En CUDA: Kernel = función.● Un kernel se ejecuta en paralelo a

través threads paralelos.

Page 25: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

CUDA ● Cómo es la parte paralela de la aplicación?

El programador decide:

“el kernel A será ejecutado por n threads”

● Un programa CUDA invoca a funciones paralelas

llamadas kernels. En CUDA: Kernel = función.● Un kernel se ejecuta en paralelo a

través threads paralelos.

A

B

C…

+ + + + + + +

=

Con n threads que cada uno sumeun elemento del vector resultante, consigo ejecutar la suma de vectores en un único paso !!

Page 26: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

CUDA

● Un programa CUDA invoca a kernels paralelos. ● Un kernel se ejecuta en paralelo a través threads paralelos.

Múltiples threads ejecutandoel mismo kernel.

A

B

C…

+ + + + + + +

=

Page 27: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

CUDA

● Tenemos programas CUDA híbridos, que se ejecutan en CPU y GPU.

● Tenemos dos arquitecturas que se conectan mediante un conector PCI-Express (no comparten espacio de direccionamiento)

Page 28: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

¿Cómo lo hacemos con CUDA? ● Este problema ahora implica:

– Inicialización de arreglos en CPU

– Transferencia de datos CPU → GPU

Page 29: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

¿Cómo lo hacemos con CUDA? ● Este problema ahora implica:

– Inicialización de arreglos en CPU

– Transferencia de datos CPU → GPU

– Cálculo de la suma en paralelo.

Page 30: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

¿Cómo lo hacemos con CUDA? ● Este problema ahora implica:

– Inicialización de arreglos en CPU

– Transferencia de datos CPU → GPU

– Cálculo de la suma en paralelo.

– Transferencia de datos GPU → CPU.

Page 31: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

¿Cómo lo hacemos con CUDA? ● Este problema ahora implica:

– Inicialización de arreglos en CPU

– Transferencia de datos CPU → GPU

– Cálculo en GPU.

– Transferencia de datos GPU → CPU.

Modelo de programación

CUDA

Page 32: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Modelo de programación CUDA

CUDA extiende al lenguaje C/C++ incluyendo dos característicasprincipales:

- Organización y manejo de threads concurrentes.

- Manejo de jerarquía de memorias instaladas en la GPU.

Page 33: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

● Jerarquía de threads:– thread,

CUDA extiende al lenguaje C/C++ incluyendo dos característicasprincipales:

- Organización y manejo de threads concurrentes.

thread

Page 34: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

● Jerarquía de threads:– thread,

– bloque,

CUDA extiende al lenguaje C/C++ incluyendo dos característicasprincipales:

- organización y manejo de threads concurrentes.

thread

bloque 1, 2 o 3 dimensiones

Page 35: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

● Jerarquía de threads:– thread,

– bloque

– grilla.

CUDA extiende al lenguaje C/C++ incluyendo dos característicasprincipales:

- organización y manejo de threads concurrentes.

thread

bloque

grilla

1, 2 o 3 dimensiones

1, 2 o 3 dimensiones

Grid 1

Block (0,0)

Block (2,0)

Block (1,0)

Block (0,0)

Block (1,0)

Grid 2

Block (0,1)

Block (1,1)

grilla

Page 36: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

● Memorias: – Privada de cada thread.

CUDA extiende al lenguaje C/C++ incluyendo dos característicasprincipales:

- Manejo de jerarquía de memorias instaladas en la GPU

Memoria localde thread

Page 37: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

● Memorias: – Privada de cada thread.

– Compartida por bloque.

CUDA extiende al lenguaje C/C++ incluyendo dos característicasprincipales:

- Manejo de jerarquía de memorias instaladas en la GPU

Memoria localde thread

Memoria compartidade bloque

Page 38: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

● Memorias: – Privada de cada thread.

– Compartida por bloque.

– Global de toda la aplicación

CUDA extiende al lenguaje C/C++ incluyendo dos característicasprincipales:

- Manejo de jerarquía de memorias instaladas en la GPU

Grid 1

Block (0,0)

Block (2,0)

Block (1,0)

Block (0,0)

Block (1,0)

Grid 2

Block (0,1)

Block (1,1)

Memoria localde thread

Memoria compartidade bloque

Memoria global

Page 39: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

- Manejo de jerarquía de memorias instaladas en la GPU

● CUDA ofrece distintas memorias con distintas características:

– Registros

– Memoria compartida

– Memoria global

– Memoria constante.

● Algunas de ellas están en caché.

Page 40: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

● Memoria Global: es la más grande y la más lenta. Puede ser leída y escrita por la CPU y por los threads de GPU. Permite comunicar datos entre CPU y GPU. El patrón de acceso a memoria por los threads puede afectar el rendimiento.

● Memoria Constante: es parte de la memoria global. CPU puede leer y escribir, y es sólo de lectura para GPU threads. Ofrece mayor ancho de banda cuando grupos de threads acceden al mismo dato.

● Memoria compartida: es pequeña y muy rápida y es compartida por todos los threads de un bloque. Es de lectura/escritura por los threads. Puede comunicar datos entre threads del mismo bloque. Puede verse afectada por el patrón de acceso de los threads.

● Registros: cada thread utiliza su propio conjunto de registros. El programador no tiene control explícito de los registros, y son utilizados para la ejecución de programas de la misma forma que los registros de propósito general de CPU.

● Memoria local: es usada por el compilador automáticamente para alojar variables cuando hace falta.

● Memoria de textura: es controlada por el programador y puede beneficiar aplicaciones con localidad espacial donde el acceso a memoria global es un cuello de botella.

Page 41: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: suma de vectores. Código que se ejecuta en host.

*/

main.cu

int main(){ /* alocacion de memoria en host */ float *h_A = (float *) malloc(N * sizeof(float)); float *h_B = (float *) malloc(N * sizeof(float)); float *h_aux = (float *) malloc(N * sizeof(float));

/* alocacion de memoria en device */ float *d_A, *d_B; cudaMalloc((void**)&d_A, sizeof(float) * N); cudaMalloc((void**)&d_B, sizeof(float) * N);

/* chequeo de alocacion de memoria */ if (!h_A || !h_B || !d_A || !d_B || !h_aux) { printf("Error alocando vectores \n"); exit(-1); }

main.cu

Page 42: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: suma de vectores. Código que se ejecuta en host.

*/

int main(){ /* alocacion de memoria en host */ float *h_A = (float *) malloc(N * sizeof(float)); float *h_B = (float *) malloc(N * sizeof(float)); float *h_aux = (float *) malloc(N * sizeof(float));

/* alocacion de memoria en device */ float *d_A, *d_B; cudaMalloc((void**)&d_A, sizeof(float) * N); cudaMalloc((void**)&d_B, sizeof(float) * N);

/* chequeo de alocacion de memoria */ if (!h_A || !h_B || !d_A || !d_B || !h_aux) { printf("Error alocando vectores \n"); exit(-1); }

Alocación de memoria dinámica en host

main.cu

Page 43: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: suma de vectores. Código que se ejecuta en host.

*/

int main(){ /* alocacion de memoria en host */ float *h_A = (float *) malloc(N * sizeof(float)); float *h_B = (float *) malloc(N * sizeof(float)); float *h_aux = (float *) malloc(N * sizeof(float));

/* alocacion de memoria en device */ float *d_A, *d_B; cudaMalloc((void**)&d_A, sizeof(float) * N); cudaMalloc((void**)&d_B, sizeof(float) * N);

/* chequeo de alocacion de memoria */ if (!h_A || !h_B || !d_A || !d_B || !h_aux) { printf("Error alocando vectores \n"); exit(-1); }

Alocación de memoria en device

main.cu

Aloca n bytes en memoria globaldel device los cuales serán apunta-dos por d_A (d_B respectivamente)

Page 44: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: suma de vectores. Código que se ejecuta en host.

*/

int main(){ /* alocacion de memoria en host */ float *h_A = (float *) malloc(N * sizeof(float)); float *h_B = (float *) malloc(N * sizeof(float)); float *h_aux = (float *) malloc(N * sizeof(float));

/* alocacion de memoria en device */ float *d_A, *d_B; cudaMalloc((void**)&d_A, sizeof(float) * N); cudaMalloc((void**)&d_B, sizeof(float) * N);

/* chequeo de alocacion de memoria */ if (!h_A || !h_B || !d_A || !d_B || !h_aux) { printf("Error alocando vectores \n"); exit(-1); }

main.cu

Page 45: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Continuación del código anterior

*/

/* inicializacion de vectores */ printf("Inicializacion vector A \n"); vector_io_initializeRND(h_A, N); printf("Inicializacion vector B \n"); vector_io_initializeRND(h_B, N);

/* transferencia de datos cpu -> gpu (host -> device) */ cudaMemcpy(d_A, h_A, sizeof(float) * N, cudaMemcpyHostToDevice); cudaMemcpy(d_B, h_B, sizeof(float) * N, cudaMemcpyHostToDevice);

main.cu

Page 46: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Continúa código anterior

*/

/* inicializacion de vectores */ printf("Inicializacion vector A \n"); vector_io_initializeRND(h_A, N); printf("Inicializacion vector B \n"); vector_io_initializeRND(h_B, N);

/* transferencia de datos cpu -> gpu (host -> device) */ cudaMemcpy(d_A, h_A, sizeof(float) * N, cudaMemcpyHostToDevice); cudaMemcpy(d_B, h_B, sizeof(float) * N, cudaMemcpyHostToDevice);

main.cu

Page 47: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Continúa código anterior

*/

/* inicializacion de vectores */ printf("Inicializacion vector A \n"); vector_io_initializeRND(h_A, N); printf("Inicializacion vector B \n"); vector_io_initializeRND(h_B, N);

/* transferencia de datos cpu -> gpu (host -> device) */ cudaMemcpy(d_A, h_A, sizeof(float) * N, cudaMemcpyHostToDevice); cudaMemcpy(d_B, h_B, sizeof(float) * N, cudaMemcpyHostToDevice);

CPU

Memoriaprincipal

GPU

Memoriaglobal

I/O

main.cu

Page 48: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Continúa código anterior

*/

/* inicializacion de vectores */ printf("Inicializacion vector A \n"); vector_io_initializeRND(h_A, N); printf("Inicializacion vector B \n"); vector_io_initializeRND(h_B, N);

/* transferencia de datos cpu -> gpu (host -> device) */ cudaMemcpy(d_A, h_A, sizeof(float) * N, cudaMemcpyHostToDevice); cudaMemcpy(d_B, h_B, sizeof(float) * N, cudaMemcpyHostToDevice);

CPU

Memoriaprincipal

GPU

Memoriaglobal

I/O

main.cu

Page 49: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: suma de vectores. Código que se ejecuta en host.

*/

Copia datos dehost a device

CPU

Memoriaprincipal

GPU

Memoriaglobal

I/O

/* inicializacion de vectores */ printf("Inicializacion vector A \n"); vector_io_initializeRND(h_A, N); printf("Inicializacion vector B \n"); vector_io_initializeRND(h_B, N);

/* transferencia de datos cpu -> gpu (host -> device) */ cudaMemcpy(d_A, h_A, sizeof(float) * N, cudaMemcpyHostToDevice); cudaMemcpy(d_B, h_B, sizeof(float) * N, cudaMemcpyHostToDevice);

main.cu

Page 50: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: suma de vectores. Código que se ejecuta en host.

*/

Copia datos dehost a device

/* inicializacion de vectores */ printf("Inicializacion vector A \n"); vector_io_initializeRND(h_A, N); printf("Inicializacion vector B \n"); vector_io_initializeRND(h_B, N);

/* transferencia de datos cpu -> gpu (host -> device) */ cudaMemcpy(d_A, h_A, sizeof(float) * N, cudaMemcpyHostToDevice); cudaMemcpy(d_B, h_B, sizeof(float) * N, cudaMemcpyHostToDevice);

main.cu

cudaMemcpy(destino, origen, size, DIRECCION_COPIA)

Copia size bytes desde la dirección origen a la direccióndestino en la memoria global. DIRECCION_COPIA indicael sentido de la copia: - cudaMemcpyHostToHost. - cudaMemcpyHostToDevice. - cudaMemcpyDeviceToHost. - cudaMemcpyDeviceToDevice.

Page 51: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: suma de vectores. Código que se ejecuta en host.

*/

CPU

Memoriaprincipal

GPU

Memoriaglobal

I/O

/* inicializacion de vectores */ printf("Inicializacion vector A \n"); vector_io_initializeRND(h_A, N); printf("Inicializacion vector B \n"); vector_io_initializeRND(h_B, N);

/* transferencia de datos cpu -> gpu (host -> device) */ cudaMemcpy(d_A, h_A, sizeof(float) * N, cudaMemcpyHostToDevice); cudaMemcpy(d_B, h_B, sizeof(float) * N, cudaMemcpyHostToDevice);

Tenemos los datos alocados en memoria principal de la CPU y en memoria global de GPU.

Estamos listos para operar en device.

main.cu

Page 52: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

main.cu

/* suma secuencial */ printf("Suma secuencial (CPU)\n"); suma_secuencial(h_A, h_B, N);

/* suma paralela */ printf("Suma paralela (GPU) \n"); suma_paralela(d_A, d_B, N);

/* traigo los datos desde GPU a CPU para testear la suma */ cudaMemcpy(h_aux, d_A, sizeof(float) * N, cudaMemcpyDeviceToHost);

if(vector_ops_iguales(h_aux, h_A, N)) printf("Test pasado! \n"); else printf("Test no pasado! \n");

/* liberacion de memoria */ free(h_A); free(h_B); free(h_aux); cudaFree(d_A); cudaFree(d_B);

return 0;}

Page 53: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

/* suma secuencial */ printf("Suma secuencial (CPU)\n"); suma_secuencial(h_A, h_B, N);

/* suma paralela */ printf("Suma paralela (GPU) \n"); suma_paralela(d_A, d_B, N);

/* traigo los datos desde GPU a CPU para testear la suma */ cudaMemcpy(h_aux, d_A, sizeof(float) * N, cudaMemcpyDeviceToHost);

if(vector_ops_iguales(h_aux, h_A, N)) printf("Test pasado! \n"); else printf("Test no pasado! \n");

/* liberacion de memoria */ free(h_A); free(h_B); free(h_aux); cudaFree(d_A); cudaFree(d_B);

return 0;}

Función secuencial, ya vista

main.cu

Page 54: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

/* suma secuencial */ printf("Suma secuencial (CPU)\n"); suma_secuencial(h_A, h_B, N);

/* suma paralela */ printf("Suma paralela (GPU) \n"); suma_paralela(d_A, d_B, N);

/* traigo los datos desde GPU a CPU para testear la suma */ cudaMemcpy(h_aux, d_A, sizeof(float) * N, cudaMemcpyDeviceToHost);

if(vector_ops_iguales(h_aux, h_A, N)) printf("Test pasado! \n"); else printf("Test no pasado! \n");

/* liberacion de memoria */ free(h_A); free(h_B); free(h_aux); cudaFree(d_A); cudaFree(d_B);

return 0;}

Función paralela

main.cu

Page 55: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Función que invoca al kernel (desde CPU se invoca a kernel (GPU))

*//* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

vector_ops.c

Page 56: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Función que invoca al kernel (desde CPU se invoca a kernel (GPU))

*/

Configuracióndel grid

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

vector_ops.c

Variables de tipo dim3: vector de 3 enteros que se usa para especificar dimensiones. Componentes x, y, z. Si algún componente no se inicializa → 1.

Page 57: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Función que invoca al kernel (desde CPU se invoca a kernel (GPU))

*/

Configuracióndel grid

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

vector_ops.c

Variables de tipo dim3: vector de 3 enteros que se usa para especificar dimensiones. Componentes x, y, z. Si algún componente no se inicializa → 1.

nThreads → especificará cantidad de threads por bloque.nBlocks → especificará cantidad de bloques en el grid

Page 58: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Función que invoca al kernel (desde CPU se invoca a kernel (GPU))

*/

Configuracióndel grid

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

vector_ops.c

Variables de tipo dim3: vector de 3 enteros que se usa para especificar dimensiones. Componentes x, y, z. Si algún componente no se inicializa → 1.

nThreads → especificará cantidad de threads por bloque (bloques de 1, 2 o 3 dimensiones).nBlocks → especificará cantidad de bloques en el grid (grids de 1, 2 o 3 dimensiones)

¿Cómo queda configurado el grid?

Page 59: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

● Kernel 1:– dim3 dimGrid(3,2)

– dim3 dimBlock(5,3)

● Kernel 2:– dim3 dimGrid(4,3)

– Dim3 dimBlock(?,?,?)

Page 60: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Función (se ejecuta en CPU) que invoca al kernel (se ejecuta en GPU)

*/

Lanzamientodel kernel

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

vector_ops.c

Page 61: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Función (se ejecuta en CPU) que invoca al kernel (se ejecuta en GPU)

*/

Lanzamientodel kernel

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

vector_ops.c

nombre_Kernel<<<número de bloques, threads por bloque>>>(parámetros actuales);

Page 62: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Función (se ejecuta en CPU) que invoca al kernel (se ejecuta en GPU)

*/

Kernel

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

/* suma de cada elemento del vector */__global__ void kernel_suma(float *v1, float *v2, int dim){ int id = threadIdx.x + (blockIdx.x * blockDim.x);

if (id < dim) { v1[id] = v1[id] + v2[id]; }}

vector_ops.c

Page 63: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

/* suma de cada elemento del vector */__global__ void kernel_suma(float *v1, float *v2, int dim){ int id = threadIdx.x + (blockIdx.x * blockDim.x);

if (id < dim) { v1[id] = v1[id] + v2[id]; }}

vector_ops.c

__global__: calificador de función

Page 64: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Calificadores de funciones:

__global__: determina que es una función kernel, se ejecuta en el dispositivo y sólo puede ser invocada desde el host. Su invocación genera un grid de bloques con número fijo e igual de threads.

__device__ : es una función del dispositivo, se ejecuta en él y sólo puede ser invocada desde un kernel u otra función del dispositivo.

__host__ : determina que es una función del host, o simplemente una función de C tradicional a ejecutarse en host y que puede ser invocada desde host. Por omisión.

Page 65: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

vector_ops.c

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

/* suma de cada elemento del vector */__global__ void kernel_suma(float *v1, float *v2, int dim){ int id = threadIdx.x + (blockIdx.x * blockDim.x);

if (id < dim) { v1[id] = v1[id] + v2[id]; }}

Page 66: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Variables reservadas:

gridDim: contiene las dimensiones del grid.

blockIdx : contiene el identificador del bloque en un grid.

blockDim: contiene las dimensiones del bloque.

threadIdx: contiene el identificador del thread dentro del bloque.

Todas tienen componentes x,y,z.

Grids y bloques de 1, 2 o 3 dimensiones.

Page 67: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

vector_ops.c

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

/* suma de cada elemento del vector */__global__ void kernel_suma(float *v1, float *v2, int dim){ int id = threadIdx.x + (blockIdx.x * blockDim.x);

if (id < dim) { v1[id] = v1[id] + v2[id]; }}

Page 68: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

vector_ops.c

/* Suma de vectores. Resultado queda en el primer argumento */int vector_ops_suma_par(float *v1, float *v2, int dim){ dim3 nThreads(512); dim3 nBlocks((dim / nThreads.x) + (dim % nThreads.x ? 1 : 0));

kernel_suma<<<nBlocks, nThreads>>>(v1, v2, dim);

cudaDeviceSynchronize();

return 1;}

/* suma de cada elemento del vector */__global__ void kernel_suma(float *v1, float *v2, int dim){ int id = threadIdx.x + (blockIdx.x * blockDim.x);

if (id < dim) { v1[id] = v1[id] + v2[id]; }}

Cada thread resuelveun único elemento delvector.

Page 69: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

main.cu

/* suma secuencial */ printf("Suma secuencial (CPU)\n"); suma_secuencial(h_A, h_B, N);

/* suma paralela */ printf("Suma paralela (GPU) \n"); suma_paralela(d_A, d_B, N);

/* traigo los datos desde GPU a CPU para testear la suma */ cudaMemcpy(h_aux, d_A, sizeof(float) * N, cudaMemcpyDeviceToHost);

if(vector_ops_iguales(h_aux, h_A, N)) printf("Test pasado! \n"); else printf("Test no pasado! \n");

/* liberacion de memoria */ free(h_A); free(h_B); free(h_aux); cudaFree(d_A); cudaFree(d_B);

return 0;}

Page 70: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

main.cu

/* suma secuencial */ printf("Suma secuencial (CPU)\n"); suma_secuencial(h_A, h_B, N);

/* suma paralela */ printf("Suma paralela (GPU) \n"); suma_paralela(d_A, d_B, N);

/* traigo los datos desde GPU a CPU para testear la suma */ cudaMemcpy(h_aux, d_A, sizeof(float) * N, cudaMemcpyDeviceToHost);

if(vector_ops_iguales(h_aux, h_A, N)) printf("Test pasado! \n"); else printf("Test no pasado! \n");

/* liberacion de memoria */ free(h_A); free(h_B); free(h_aux); cudaFree(d_A); cudaFree(d_B);

return 0;}

Page 71: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

main.cu

/* suma secuencial */ printf("Suma secuencial (CPU)\n"); suma_secuencial(h_A, h_B, N);

/* suma paralela */ printf("Suma paralela (GPU) \n"); suma_paralela(d_A, d_B, N);

/* traigo los datos desde GPU a CPU para testear la suma */ cudaMemcpy(h_aux, d_A, sizeof(float) * N, cudaMemcpyDeviceToHost);

if(vector_ops_iguales(h_aux, h_A, N)) printf("Test pasado! \n"); else printf("Test no pasado! \n");

/* liberacion de memoria */ free(h_A); free(h_B); free(h_aux); cudaFree(d_A); cudaFree(d_B);

return 0;}

Page 72: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores/*

Main.cu: continuación del código.

*/

main.cu

/* suma secuencial */ printf("Suma secuencial (CPU)\n"); suma_secuencial(h_A, h_B, N);

/* suma paralela */ printf("Suma paralela (GPU) \n"); suma_paralela(d_A, d_B, N);

/* traigo los datos desde GPU a CPU para testear la suma */ cudaMemcpy(h_aux, d_A, sizeof(float) * N, cudaMemcpyDeviceToHost);

if(vector_ops_iguales(h_aux, h_A, N)) printf("Test pasado! \n"); else printf("Test no pasado! \n");

/* liberacion de memoria */ free(h_A); free(h_B); free(h_aux); cudaFree(d_A); cudaFree(d_B);

return 0;}

Page 73: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Suma de vectores

A

a0 a1 a2 a3 aN-1

B

b0 b1 b2 b3 bN-1…

C

c0 c1 c2 c3 cN-1…

+ + + + + + +

De orden lineal a orden constante!!

=

Y se resuelve en paralelo todos losresultados del vector.

th0 th1 th2 th3 thN-1…

Page 74: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Modelo de programación CUDA

No todos los problemas pueden ser resueltos usando placas de tipo GPU.

Los más adecuados son los que aplican la misma secuencia de código a los datos de entrada.

Page 75: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Modelo de programación CUDA

Ganaremos con GPU si:

El algoritmo tiene orden de ejecución cuadrático o superior: compensar el tiempo de transferencia de datos CPU – GPU.

Gran carga de cálculo en cada thread (por lo mismo que el itemanterior).

Poca dependencia de datos. Independencia de cómputo. Puede llevar aacceso a su memoria local o compartida y evita acceder a la global (costosa).

Mínima transferencia de datos CPU-GPU: óptimo: principio y final. Evitar tranferencias intermedias, ya sean para resultados parcialeso datos de entrada intermedios.

No existan secciones críticas: lecturas paralelas a datos, pero no escrituras: necesitamos mecanismos de acceso seguro → secuen-cialización de accesos.

Page 76: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Resumen

Hemos visto: - Alocación de memoria en device.- Transferencia de memoria host ↔ device.- Configuración de grid.- Lanzamiento de kernels.

Todas estas operaciones las ofrece CUDA como una libreríaque extiende al lenguaje C (en este caso).

Page 77: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Probando el código

1) Copiar la carpeta /share/apps/codigos/SUMA-Vectores a la carpeta personal:

[mdenham@gpgpu-fisica ~]$ cp -a /share/apps/codigos/SUMA-Vectores/ .

2) Para compilar: los paquetes de compiladores/ bibliotecas se usan via el comando module. Para compilar con CUDA debemos cargar el módulo:

[mdenham@gpgpu-fisica SUMA-Vectores]$ module load cuda

Entrar a la carpeta local SUMA-Vectores y compilar:

[mdenham@gpgpu-fisica SUMA-Vectores]$ cd SUMA-Vectores[mdenham@gpgpu-fisica SUMA-Vectores]$ make

Page 78: Primeros pasos con CUDA - fisica.cab.cnea.gov.arfisica.cab.cnea.gov.ar/gpgpu/images/clases/clase_1_cuda.pdf · - Manejo de jerarquía de memorias instaladas en la GPU Memoria local

Probando el código

3) Ejecutar la aplicación: encolamos el ejecutable main usando el scriptsubmit_gpuh.sh:

[mdenham@gpgpu-fisica ~]$ qsub submit_gpuh.sh

4) Para consultar el estado de los trabajos lanzados:

[mdenham@gpgpu-fisica SUMA-Vectores]$ qstat -f [mdenham@gpgpu-fisica SUMA-Vectores]$ qstat -u '*'

5) Verificar resultados: ver los resultados en submit_gpuh.sh.o*****

[mdenham@gpgpu-fisica SUMA-Vectores]$ cat submit_gpuh.sh.o***