ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se...
Transcript of ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se...
![Page 1: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/1.jpg)
3EAGPGPU3EAGPGPU
CUDA Básico
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
3EAGPGPU3EAGPGPU
Pablo Pablo EzzattiEzzatti
![Page 2: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/2.jpg)
Parte B
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
![Page 3: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/3.jpg)
ContenidoContenido
• Conceptos básicos de programación paralela
• Modelo de programación CUDA
• Programación CUDA básico
– Conceptos básicos
– Estrategias de memoria compartida
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
![Page 4: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/4.jpg)
Conceptos básicos de
Programación Paralela
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
Programación Paralela
![Page 5: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/5.jpg)
Conceptos Básicos de Programación Paralela
• Múltiples unidades de cómputo trabajando en forma
coordinada
• Comunicación
• Sincronización
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• División
• De tareas
• De datos
![Page 6: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/6.jpg)
Conceptos Básicos de Programación Paralela
• Paralelismo de
• Memoria compartida (multi-core)
• Memoria distribuida (cluster)
• Contexto
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Contexto
• Homogéneo
• Heterogéneo
• Balance de carga
![Page 7: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/7.jpg)
Conceptos Básicos de Programación Paralela
En este caso:
• Muchas unidades de cómputo trabajando en forma
coordinada.
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• División de datos.
• Paralelismo “similar” a paralelismo a memoria compartida
(multi-core).
• Unidades de procesamiento homogéneas.
![Page 8: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/8.jpg)
Conceptos Básicos de Programación Paralela
En los ejemplos que se verán a continuación:
• Se utilizará una sintaxis inspirada en la de Matlab.
• El código escrito en color negro ejecuta en forma secuencial.
• El código escrito en color indica palabras reservadas que son
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• El código escrito en color azul indica palabras reservadas que son
directivas para el manejo de paralelismo.
• El código escrito en color rojo indica el punto de ramificación del
paralelismo.
• El código escrito en color verde es el código que es ejecutado en forma
paralela por cada una de las unidades de procesamiento.
![Page 9: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/9.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 0:
• Se tiene una matriz con
4 columnas y se quiere
obtener la suma por
columnas de la matriz.
• Se dispone de una única
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Se dispone de una única
unidad de
procesamiento.
![Page 10: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/10.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 0:
Res = zeros(1,4)
[m,n] = size(Mat)
For j = 1:4
For i = 1 : m
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
For i = 1 : m
Res(j) = Res(j) + Mat(i,j)
![Page 11: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/11.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 1:
• Se tiene una matriz con
4 columnas y se quiere
obtener la suma por
columnas de la matriz.
• Se dispone de cuatro
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Se dispone de cuatro
unidades de
procesamiento.
![Page 12: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/12.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 1:
Res = zeros(1,4)
[m,n] = size(Mat)
begin_parallel(4)
For j = 1:4
For i = 1 : m
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
For i = 1 : m
Res(j) = Res(j) + Mat(i,j)
end_parallel
![Page 13: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/13.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 2:
• Se tiene una matriz con 400 columnas y se quiere obtener la
suma por columnas de la matriz.
• Se dispone de cuatro unidades de procesamiento.
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
![Page 14: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/14.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 2:
Res = zeros(1,400)
[m,n] = size(Mat)
begin_parallel(4)
For j = 1:400
For i = 1 : m
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
For i = 1 : m
Res(j) = Res(j) + Mat(i,j)
end_parallel
![Page 15: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/15.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 3:
• Se tiene una matriz cuadrada con 400 columnas y se quiere
obtener la suma por columnas de la matriz triangular superior.
• Se dispone de cuatro unidades de procesamiento.
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
![Page 16: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/16.jpg)
Conceptos Básicos de Programación Paralela
Distribución de datos/cálculos
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
Distribución por bloque Distribución cíclica
![Page 17: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/17.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 3:
• Es posible achicar el tamaño de los bloques.
• Por ejemplo: de 100 columnas pasar a 10 columnas por bloque.
Res = zeros(1,400)
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
[m,n] = size(Mat)
begin_parallel(40,cyc)
For j = 1:400
For i = 1 : j
Res(j) = Res(j) + Mat(i,j)
end_parallel
![Page 18: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/18.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 4:
• Se tiene una matriz con 400 columnas y se quiere obtener la
suma por columnas de la matriz.
• Se dispone de cuatro unidades de procesamiento.
• En este caso, además se quiere obtener la suma parcial por
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• En este caso, además se quiere obtener la suma parcial por
unidad de procesamiento.
![Page 19: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/19.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 4:
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
![Page 20: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/20.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 4:
Res = zeros(1,400)
Res2 = zeros(1,4)
[m,n] = size(Mat)
begin_parallel(40)
For j = 1:400
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
For j = 1:400
private idP = myId()
For i = 1 : j
Res(j) = Res(j) + Mat(i,j)
Res2(idP) = Res2(idP) + Res(j)
end_parallel
![Page 21: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/21.jpg)
Conceptos Básicos de Programación Paralela
Ejemplo 5:
• Se tiene una matriz con 400 columnas y se quiere obtener la
suma de todos los elementos de la matriz.
• Se dispone de cuatro unidades de procesamiento.
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Se dispone de cuatro unidades de procesamiento.
![Page 22: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/22.jpg)
Conceptos Básicos de Programación Paralela
Solución 1
• Se suma por columna
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Luego se suma todo el vector intermedio
![Page 23: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/23.jpg)
Conceptos Básicos de Programación Paralela
Solución 1
• Se suma por columna y luego se suma el vector intermedio.
Res = zeros(1,400)
[m,n] = size(Mat)
begin_parallel (4)
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
begin_parallel (4)
For j = 1:400
For i = 1 : m
Res(j) = Res(j) + Mat(i,j)
end_parallel
For j = 1:400
Sum = Sum + Res(j)
![Page 24: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/24.jpg)
Conceptos Básicos de Programación Paralela
Solución 2
• Se suma por columnas para cada unidad de procesamiento.
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Luego se suma el vector intermedio.
![Page 25: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/25.jpg)
Conceptos Básicos de Programación Paralela
Solución 2
• Se suma por columnas
para cada unidad de
procesamiento y luego
se suma el vector
intermedio.
Res = zeros(1,4)
[m,n] = size(Mat)
begin_parallel(4)
For j = 1:400
private idP = myId ()
For i = 1 : m
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
intermedio. For i = 1 : m
Res(idP) = Res(idP) + Mat(i,j)
end_parallel
For j = 1:4
Sum = Sum + Res(j)
![Page 26: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/26.jpg)
Conceptos Básicos de Programación Paralela
Solución 3
• Sumo por columna
y actualizo el
resultado.
Res = zeros(1,4)
[m,n] = size(Mat)
begin_parallel(4)
For j = 1:400
private idP = myId ()
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Concepto de
reduce
For i = 1 : m
Res(idP) = Res(idP) + Mat(i,j)
end_parallel
begin_parallel(2)
For j = 1:4
Sum = Sum + Res(j)
end_parallel
![Page 27: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/27.jpg)
Conceptos Básicos de Programación Paralela
Race condition:
- Los hilos compiten por
el acceso a los
registros.
- Pueden haber distintos
ordenes de ejecución.
Res = zeros(1,4)
[m,n] = size(Mat)
begin_parallel(4)
For j = 1:400
private idP = myId ()
For i = 1 : m
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
ordenes de ejecución.
- Distinto orden de
ejecución produce
resultados
diferentes!!!
- Este problema también
aparece en circuitos
electrónicos, base de
datos, etc.
For i = 1 : m
Res(idP) = Res(idP) +Mat(i,j)
end_parallel
begin_parallel(2)
For j = 1:4
Sum = Sum + Res(j)
end_parallel
![Page 28: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/28.jpg)
Conceptos Básicos de Programación Paralela
[m,n] = size(Mat)
begin_parallel(4)
private Res
For j = 1:400
Reduce:
- Generalmente están
disponibles diversas
operaciones:
• +
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
%private idP = myId ()
For i = 1 : m
Res = Res + Mat(i,j)
end_parallel (reduce(+,Res) )
• +
• *
• min
• max
![Page 29: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/29.jpg)
Conceptos Básicos de Programación Paralela
Consideremos el
siguiente código:
• Hay problemas por el
acceso concurrente a
la variable aux.
Res = zeros(1,11)
aux = 11
begin_parallel(400)
For j = 1:400
if ( aux == 1)
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
if ( aux == 1)
aux = aux + 10
else
aux = aux - 1
end
Res(aux) = Res(aux) +Mat(aux,j)
end_parallel
![Page 30: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/30.jpg)
Conceptos Básicos de Programación Paralela
Diferentes formas de
resolverlo:
• Semáforos
• Zonas mutuo
excluidas
Res = zeros(1,11)
aux = 11
begin_parallel(400)
For j = 1:400
if ( aux == 1)
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
excluidas
• Operaciones atómicas
if ( aux == 1)
aux = aux + 10
else
aux = aux - 1
end
Res(aux) = Res(aux) + Mat(aux,j)
end_parallel
![Page 31: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/31.jpg)
Conceptos Básicos de Programación Paralela
Res = zeros(1,11)
begin_parallel(400)
For j = 1:400
begin_mutex()
if (aux == 1)
aux = aux + 10
Con zonas mutuo
excluidas
Solo un “hilo de
ejecución” entra en la
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
aux = aux + 10
else
aux = aux - 1
end
Res(aux) = Res(aux) +Mat(aux,j)
end_mutex()
end_parallel
ejecución” entra en la
zona.
![Page 32: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/32.jpg)
Conceptos Básicos de Programación Paralela
Res = zeros(1,400)
[m,n] = size(Mat)
begin_parallel(4)
Operaciones atómicas
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
For j = 1:400
For i = 1 : m
Res(j) = Res(j) + Mat(i,j)
Sum = Sum + Res(j)
end_parallel
![Page 33: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/33.jpg)
Conceptos Básicos de Programación Paralela
Res = zeros(1,400)
[m,n] = size(Mat)
begin_parallel(4)
For j = 1:400
For i = 1 : m
Operaciones atómicas
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
For i = 1 : m
Res(j) = Res(j) + Mat(i,j)
begin_atomic()
Sum = Sum + Res(j)
end_atomic()
end_parallel
![Page 34: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/34.jpg)
Conceptos Básicos de Programación Paralela
Diferentes caminos dependiendo del thread
begin_parallel(400)
For j = 1:400
private idP = myId ()
if ( mod(idP,2) == 0)
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Estrategia comúnmente utilizada para implementar el modelo de
paralelismo Maestro-Esclavo: if soyMaestro()
if ( mod(idP,2) == 0)
Mat(j) = Mat(j) + 4
else
Mat(j) = Mat(j) + 2
end
end_parallel
![Page 35: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/35.jpg)
Conceptos Básicos de Programación Paralela
Conceptos vistos
• Paralelismo
• Estrategias de scheduling y balance de carga
• Distribución de datos/cálculos
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Distribución de datos/cálculos
• Utilizar información del thread/proceso/etc.
• Reducciones
• Race conditions
• Operaciones atómicas
e
![Page 36: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/36.jpg)
Conceptos Básicos de Programación Paralela
Es conveniente tener en cuenta:
• La importancia del scheduling, distribución de
datos/cálculos y control de sincronizaciones para un
buen desempeño.
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
buen desempeño.
• Si bien parece obvio, además de buen desempeño es
necesario correctitud. Sin embargo, esto es más
complejo de comprobar que en programas secuenciales.
![Page 37: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/37.jpg)
Modelo de programación CUDA
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
![Page 38: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/38.jpg)
IntroducciónIntroducción
El device:
• Es un coprocesador de la CPU (host).
• Posee su propia memoria DRAM (memoria del device).
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Ejecuta “muchos” threads en paralelo.
Una porción de los cálculos con paralelismo de datos se computan
con kernels en el device que corren en “muchos” threads.
![Page 39: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/39.jpg)
IntroducciónIntroducción
Diferencias entre los threads de la GPU y CPU
• Los threads en GPU son extremadamente livianos :
Muy poco overhead para crearlos.
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
Muy poco overhead para crearlos.
• La GPU necesita 100s – 1000s de threads para alcanzar la
eficiencia:
Generalmente las CPU (multi-core ) necesitan unos pocos.
![Page 40: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/40.jpg)
IntroducciónIntroducción
Se integra código en el host con código en la tarjeta:
• El código del host puede ser secuencial o paralelo.
• En la tarjeta el código es altamente paralelo (SPMT).
Código en el host (sequencial)
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
. . .
. . .
(sequencial)
Kernel device (paralelo) KernelA<<< nBlk, nTid >>>(args);
Código en el host (paralelo)
Kernel device (paralelo) KernelB<<< nBlk, nTid >>>(args);
![Page 41: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/41.jpg)
IntroducciónIntroducción
Algoritmo básico
1. Instrucciones en el host
2. Se envían los datos del host a la GPU
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
2. Se envían los datos del host a la GPU
3. Se procesa en GPU
4. Se recuperan los datos
5. Continúan instrucciones en el host
![Page 42: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/42.jpg)
IntroducciónIntroducción
Array de threads
• Un kernel es ejecutado por un array de threads
– Todos los threads corren el mismo código (SPMT) – Cada thread tiene un ID que se puede utilizar para computar
direcciones de memoria y tomar decisiones de control
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
direcciones de memoria y tomar decisiones de control
76543210
…float x = input[threadID];float y = func(x);output[threadID] = y;…
threadID
![Page 43: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/43.jpg)
IntroducciónIntroducción
Bloques de threads
• Facilita la escalabilidad .
• Permite dividir un array de threads en múltiples bloques
• Threads en un mismo bloque cooperan via memoria
shared, operaciones atomic y barrier de sincronización.
• Threads en diferentes bloques no pueden cooperar
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Threads en diferentes bloques no pueden cooperar
directamente.
…float x = input[threadID];float y = func(x);output[threadID] = y;…
threadID
…float x = input[threadID];float y = func(x);output[threadID] = y;…
…float x = input[threadID];float y = func(x);output[threadID] = y;…
76543210 76543210
Thread Block 0 Thread Block N - 176543210
Thread Block 0
![Page 44: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/44.jpg)
IntroducciónIntroducción
Jerarquía de threads
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
![Page 45: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/45.jpg)
IntroducciónIntroducción
IDs bloque e IDs de thread
• Cada thread usa el IDs paradecidir sobre que datostrabajar
– Block ID: 1D, 2D o 3D (3D desdeFermi)
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
– Thread ID: 1D, 2D o 3D
• Puede simplificar el direccionamiento de memoria
– Procesamiento de imágenes.
– Resolución de PDEs (regulares) en 3D.
![Page 46: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/46.jpg)
IntroducciónIntroducción
Jerarquía de threads
• Los bloques dentro de un grid tienen que ser
independientes.
• Los bloques de threads son ejecutados en
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Los bloques de threads son ejecutados en
cualquier orden y en principio en diferentes
multiprocesadores.
• En las tarjetas (“nuevas”) hay ejecución
concurrente de kernels (aqui no lo vamos a tener
en cuenta !!!).
![Page 47: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/47.jpg)
Programación en CUDA
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
![Page 48: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/48.jpg)
Programación en CUDA
hostdevice__global__ void KernelFunc()
devicedevice__device__ float DeviceFunc()
Invocable
desde:
Ejecutable
en:
Las funciones
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
hosthost__host__ float HostFunc()
• __global__ define funciones “kernel”
• __device__ y __host__ pueden ser utilizados juntas
(con compilación condicional).
• __host__ puede no ponerse.
![Page 49: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/49.jpg)
Programación en CUDA
• Para invocar un kernel es necesario determinar “una
configuración de ejecución”.
__global__ void KernelFunc(...);
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
dim3 DimGrid(100, 50); // 5000 bloques
dim3 DimBlock(4, 8, 8); // 256 threads por block
size_t SharedMemBytes = 64; // 64 bytes de memoria shared
KernelFunc<<< DimGrid, DimBlock, SharedMemBytes >>>(...);
• Las llamadas a kernels son asincrónicas !!
Es necesario utilizar sincronizaciones explícitas.
![Page 50: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/50.jpg)
Programación en CUDA
Espacios de declaración de variables
Se dispone de distintos espacios (unificados) de
declaración:
• global
• _device_ residen en la memoria global del device.
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
• _device_ residen en la memoria global del device.
• _shared_ reside en la memoria shared del device.
extern _shared_ para allocamiento dinámico.
• _constant_ reside en memoria constante del device.
__device__ float filter[N]; __global__ void convolve (float *image) __shared__ float region[M];extern __shared__ float region[];
![Page 51: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/51.jpg)
Programación en CUDA
CUDA posee diversas keywords
– threadIdx (uint3) se accede con .x/.y/.z
– blockIdx (uint3) se accede con .x/.y/.z
– blockDim (dim3) se accede con .x/.y/.z
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
– blockDim (dim3) se accede con .x/.y/.z
– gridDim (dim3) se accede con .x/.y/.z
region[ threadIdx.x ] = image[i];
![Page 52: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/52.jpg)
Programación en CUDA
Funciones intrínsecas
• cudaDeviceSynchronize() : sincroniza todos los threads.
Ejecuta en el host.
• __syncthreads : permite sincronizar threads del mismo bloque.
Se invoca dentro de un kernel.
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
Se invoca dentro de un kernel.
• clock_t clock() : permite medir tiempos en el device.
Funciones matemáticas (más rápidas pero con posible diferencia
en el valor):
__sinf(x), __cosf(x), __log2f(x) …. __powf(x,y)
Funciones atómicas:
atomicAdd(), … atomicMin(), …
![Page 53: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/53.jpg)
Programación en CUDA
La API ofrece diversas funciones
• Para manejo de memoria
• Para transferencias
• Para manejo de las ejecuciones (lanzamiento)
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Para manejo de las ejecuciones (lanzamiento)
// Allocate memoria en GPU void *myimage = cudaMalloc((void**)& SDEVPTR, bytes)
![Page 54: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/54.jpg)
Programación en CUDA
CUDA Device Memory Allocation
• cudaMalloc ()
– Reserva espacio en la memoria
global del device
– Dos parámetros
• Puntero
Grid
Block (0, 0)
Shared Memory
Registers Registers
Block (1, 0)
Shared Memory
Registers Registers
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Puntero
• Tamaño de la memoria
reservada
• cudaFree ()
– Libera la memoria asociada a un
puntero en la mem. global del device
GlobalMemory
Thread (0, 0) Thread (1, 0) Thread (0, 0) Thread (1, 0)
Host
La reserva de memoria global se realiza en el host !!!
![Page 55: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/55.jpg)
Programación en CUDA
• Código de ejemplo
– Reservar una matriz de 64 * 64 floats (precisión
simple).
TILE_WIDTH = 64;
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
TILE_WIDTH = 64;float* SDEVPTRint size = TILE_WIDTH *TILE_WIDTH* sizeof(float);
cudaMalloc((void**)& SDEVPTR, size);
…..
cudaFree(SDEVPTR);
![Page 56: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/56.jpg)
Programación en CUDA
Transferencias de datos Host-Device
• cudaMemcpy()
– Transferencia de datos
– 4 parámetros
• Puntero destino
• Puntero origen
Grid
Block (0, 0)
Shared Memory
Block (1, 0)
Shared Memory
PARTE B PARTE B –– ProgramaciónProgramación I I 3EA3EAGPGPUGPGPU
• Puntero origen
• Número de bytes a copiar
• Tipo de transferencia
– Host to Host
– Host to Device
– Device to Host
– Device to Device
• Transferencias asincrónicas
GlobalMemory
Shared Memory
Thread (0, 0)
Registers
Thread (1, 0)
Registers
Shared Memory
Thread (0, 0)
Registers
Thread (1, 0)
Registers
Host
![Page 57: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/57.jpg)
Programación en CUDA
– cudaMemcpyHostToDevice y cudaMemcpyDeviceToHost
• Código de ejemplo
– Trasferir una matriz de 64 x 64 floats (precisión
simple)
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
– cudaMemcpyHostToDevice y cudaMemcpyDeviceToHostson constantes simbólicas.
cudaMemcpy(SDEVPTR, SHPTR, size, cudaMemcpyHostToDe vice);
cudaMemcpy(SHPTR, SDEVPTR, size, cudaMemcpyDeviceTo Host);
![Page 58: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/58.jpg)
Programación en CUDA
Lanzamiento
• Dimensiones de la grilla (3D): variable de tipo dim3
• Dimensiones de los bloques de threads (3D): variable de tipo dim3
• Opcionales:
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
dim3 gridSize( 16, 16 );dim3 blockSize( 32, 32 );kernel<<<gridSize, blockSize, 0, 0>>>( ... );kernel<<<32, 512>>>( ... );
• Opcionales:
• cantidad de memoria compartida por bloque
• identificador de stream
![Page 59: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/59.jpg)
Programación en CUDA
Retomando los ejemplos de programación paralela básica:
• Consideramos que se tiene una matriz con número grande de
columnas y se quiere obtener la suma por columnas de la
matriz.
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
![Page 60: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/60.jpg)
Programación en CUDA
• Ejemplo, suma por columna de los elementos de una matriz.
void SumaColMatriz(int M, int N, float * Mh, float* N h){int size = M * N * sizeof(float), size2 = N*sizeof(f loat);float* Md, *Nd;…
// Allocate en device cudaMalloc(&Md, size);cudaMalloc(&Nd, size2);
// Inicializo matrices en el device
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
// Inicializo matrices en el devicecudaMemcpy(Md, Mh, size, cudaMemcpyHostToDevice);cudaMemset(Nd ,0, size2);
// Invocar el kernel que suma en GPU
// Traer resultado ;cudaMemcpy(Nh, Nd, size2, cudaMemcpyDeviceToHost);
// Free matrices en devicecudaFree(Md); cudaFree(Nd); }
![Page 61: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/61.jpg)
Programación en CUDA
Kernel
// Suma por columnas de una matriz__global__ void SumaColMatrizKernel(int M, float* Md , float* Nd) {// Pvalue es usado para el valor intermedio
float Pvalue = 0;int aux = threadIdx.y *M;for (int k = 0; k < M; ++k) {
Pvalue = Pvalue + Md[ aux+k ];
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
Pvalue = Pvalue + Md[ aux+k ];}Nd[threadIdx.y] = Pvalue;
}
![Page 62: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/62.jpg)
Programación en CUDA
Lanzamiento del kernel
// configuración de la ejecucióndim3 tamGrid(1, 1); //Grid dimensióndim3 tamBlock(1,N,1); //Block dimensión// lanzamiento del kernel
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
// lanzamiento del kernelSumaColMatrizKernel <<<tamGrid, tamBlock>>>(M, Md, Nd);
Restricciones:
• Solo se pueden procesar matrices de tantas columnas
como threads en un bloque !!!!
• Un solo bloque, un solo multiprocesador computando.
![Page 63: ParteB - ProgramacionBasicoI · Conceptos Básicos de Programación Paralela En los ejemplos que se verán a continuación: • Se utilizará una sintaxis inspirada en la de Matlab.](https://reader034.fdocuments.net/reader034/viewer/2022042620/5f38e5a1eb576b3a5518a27f/html5/thumbnails/63.jpg)
Programación en CUDA
Vamos a la máquina 1
• Ver los códigos para el programa principal y el kernel 1.
• Compilar.
• Ejecutar.
PARTE B PARTE B –– ProgramaciónProgramación I I 33EAEAGPGPUGPGPU
• Ejecutar.