primeros pasos con cuda -...
TRANSCRIPT
![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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/1.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/2.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/3.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/4.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/5.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/6.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/7.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/8.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/9.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/10.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/11.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/12.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/13.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/14.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/15.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/16.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/17.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/18.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/19.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/20.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/21.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/22.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/23.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/24.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/25.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/26.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/27.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/28.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/29.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/30.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/31.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/32.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/33.jpg)
● 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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/34.jpg)
● 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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/35.jpg)
● 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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/36.jpg)
● 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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/37.jpg)
● 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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/38.jpg)
● 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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/39.jpg)
- 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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/40.jpg)
● 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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/41.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/42.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/43.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/44.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/45.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/46.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/47.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/48.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/49.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/50.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/51.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/52.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/53.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/54.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/55.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/56.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/57.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/58.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/59.jpg)
● 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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/60.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/61.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/62.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/63.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/64.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/65.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/66.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/67.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/68.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/69.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/70.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/71.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/72.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/73.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/74.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/75.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/76.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/77.jpg)
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](https://reader030.vdocuments.net/reader030/viewer/2022032614/5bb52dd209d3f2f2678becff/html5/thumbnails/78.jpg)
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***