Académique Documents
Professionnel Documents
Culture Documents
Ejemplos de
programacin CUDA
! Paso 1.
! __syncthreads();
! Paso 2.
Cdigo GPU
Ejecutando en paralelo
(al margen de la generacin hardware)
64
threadIdx.x
threadIdx.x
10
! Con M hilos por bloque, el ndice unvoco para cada hilo es:
! tid = threadIdx.x+ blockDim.x* blockIdx.x;
! Para acceder a un vector de un elemento por cada hilo (ya
que buscamos paralelismo de grano fino), con N=4 bloques
de M=8 hilos cada uno, tenemos:
threadIdx.x
GPU
! vecAdd<<< 1, 1 >>>():
Multiprocesador N
Ejecuta 1 bloque compuesto de
(escalabilidad en 2 gener.)
1 hilo - no hay paralelismo.
Multiprocesador 2
Multiprocesador 1
! vecAdd<<< N, 1 >>>():
Memoria compartida
Ejecuta N bloques compuestos
Registros
Registros
Registros
de 1 hilo. Paralelismo intermultiprocesador.
Core 2 Core M
Core 1
(escalabilidad en 3 gener.)
! vecAdd<<< N, M >>>():
Ejecuta N bloques compuestos
Cach de texturas
de M hilos cada uno.
Paralelismo inter- e intraMemoria global
multiprocesador.
threadIdx.x
01234567012345670123456701234567
blockIdx.x = 0 blockIdx.x = 1 blockIdx.x = 2 blockIdx.x = 3
11
Fundamento
14
13
Las buenas noticias: Los hilos pueden compartir datos y trabajar de forma coordinada
Patrn unidimensional
! Apliquemos un patrn 1D a un vector, donde el resultado
de salida es la suma de los elementos vecinos en un radio.
! Si el radio es 3, la salida es la suma de los 7 elementos
vecinos, incluyendo el propio:
radio
radio
16
El kernel de patrn
! Usar __synchthreads();
para sincronizar todos los
hilos dentro de un bloque:
// Almacena el resultado
out[gindex] = result;
}
18
// Aplica el patrn
int result = 0;
for (int offset=-RADIUS; offset<=RADIUS; offset++)
result += temp[lindex + offset];
extensin a la derecha
Debemos prevenir
condiciones de carrera. Por
ejemplo, el ltimo hilo (15)
lee del tramo extendido antes
de que el primero (0) lo haya
trado desde memoria global
a memoria compartida.
Se requiere sincronizar a los
hilos.
19
20
En resumen...
! Lanzamos N bloques con M hilos por bloque para ejecutar los hilos
en paralelo. Usar:
! kernel<<<N,M>>>();
! Calcular los ndices globales donde cada hilo tiene que trabajar
dependiendo del particionamiento de datos. Usar:
! int index = threadIdx.x + blockIdx.x * blockDim.x;
21
22
! Requiere un gran
ancho de banda.
! Tiene poca intensidad
aritmtica.
M0,0 M0,1 M0,2 M0,3 M1,0 M1,1 M1,2 M1,3 M2,0 M2,1 M2,2 M2,3 M3,0 M3,1 M3,2 M3,3
! Problemas a la vista:
N
23
24
Grid 1
Block 1
Thread
!)2 ,2(
! Cada hilo:
A
48
WIDTH
! Problemas:
N
25
26
Grid
!!!!!!!!!!!!!!!
!!!!!!!
Th(x,y)
WidthA
WidthB
Bloque
!!!!!!!
HeightA
C(x, y)
=
HeightA
WidthB
X
A
28
Ctemp=0;
for (i=0; i<widthA; i++){
Ctemp += A[indexA] * B[indexB];
indexA++;
indexB += widthB;
}
C[indexC] = Ctemp ;
! Relaja el ancho
de banda.
! Aumenta la
intensidad
aritmtica.
Csub
Memoria global
! Con tiling:
M
N
29
30
!!!!!!!!!!
SM0
As
!!!!
!!!!
!!!!
Bs
!!!!
!!!!
!!!!
8192 registros
SP0
SM15
Shared Memory
8 KB constant
!!!!!!!!!!!!!!
SFU0
SP7
SFU1
!!!!
!!!!
!!!!
!!!!
!!!!
!!!!
A
31
Memoria global
Optimizaciones adicionales:
Loop unrolling
}
C[indexC] = Ctemp ;
75
GFLOPS
Ctemp=0;
for (!!!){
__shared__ float As[16][16];
__shared__ float Bs[16][16];
100
50
Slo tiling
Tiling & Unrolling
25
0
4x4
}
C[indexC] = Ctemp ;
8x8
12x12
16x16
34