Академический Документы
Профессиональный Документы
Культура Документы
Manuel Ujaldon
Nvidia CUDA Fellow
Profesor Titular del Dpto. de Arquitectura de Computadores. Universidad de Mlaga.
Conjoint Senior Lecturer. University of Newcastle (Australia)
Contenidos del tutorial [123 diapositivas]
1. Introduccin. [17 diapositivas]
2. Arquitectura. [26]
1. El modelo hardware de CUDA. [3]
2. Primera generacin: Tesla (2007-2009). [3]
3. Segunda generacin: Fermi (2010-2011). [4]
4. Tercera generacin: Kepler (2012-2014). [16]
3. Programacin. [15]
4. Sintaxis. [16]
1. Elementos bsicos. [10]
2. Un par de ejemplos preliminares. [6]
5. Compilacin y herramientas. [12]
6. Ejemplos: VectorAdd, Stencil, MxM. [25]
7. Bibliografa, recursos y herramientas. [12] 2
Prerrequisitos para este tutorial
3
I. Introduccin
Bienvenido al mundo de las GPUs
5
Los personajes de esta historia:
La foto de familia de CUDA
6
En apenas 7 aos la programacin CUDA
ha crecido a un ritmo inusitado
Ao 2008 Ao 2014
100.000.000 de 500.000.000 de
GPUs aceptan CUDA GPUs aceptan CUDA
150.000 2.100.000 de
descargas de CUDA descargas CUDA
1 supercomputador 52
supercomputadores
60 780
cursos universitarios cursos
4.000 40.000
artculos cientficos artculos cientficos
8
Sntesis evolutiva de la GPU
Terminologa:
Host (el anfitrin): La CPU y la memoria de la placa base [DDR3].
Device (el dispositivo): La tarjeta grfica [GPU + memoria de vdeo]:
GPU: Nvidia GeForce/Tesla.
Memoria de vdeo: GDDR5 en 2013.
Host Device
13
Computacin heterognea (2/4)
CUDA ejecuta un programa sobre un dispositivo (la GPU), que acta como
coprocesador de un anfitrin o host (la CPU).
CUDA puede verse como una librera de funciones que contienen 3 tipos de
componentes:
Host: Control y acceso a los dispositivos.
Dispositivos: Funciones especficas para ellos.
Todos: Tipos de datos vectoriales y un conjunto de rutinas soportadas por ambas partes.
CPU (host)
GPU
Cores
50 GB/s.
Caches (device)
(GDDR5) 14
Computacin heterognea (3/4)
#include <iostream>
#include <algorithm>
#define N 1024
#define RADIUS 3
#define BLOCK_SIZE 16
int main(void) {
int *in, *out; // host copies of a, b, c
- Cdigo serie.
// Alloc space for device copies
cudaMalloc((void **)&d_in, size);
cudaMalloc((void **)&d_out, size);
// Copy to device
cudaMemcpy(d_in, in, size, cudaMemcpyHostToDevice);
- Cdigo paralelo.
cudaMemcpy(d_out, out, size, cudaMemcpyHostToDevice);
- Cdigo serie.
cudaMemcpy(out, d_out, size, cudaMemcpyDeviceToHost);
// Cleanup
free(in); free(out);
cudaFree(d_in); cudaFree(d_out);
return 0;
}
16
Un sencillo flujo de procesamiento (1/3)
Bus PCI
17
Un sencillo flujo de procesamiento (2/3)
PCI Bus
18
Un sencillo flujo de procesamiento (3/3)
PCI Bus
20
Hola mundo! con cdigo para la GPU (1/2)
__global__ void mikernel(void)
{ Dos nuevos elementos
} sintcticos:
int main(void) La palabra clave de CUDA __global__
{ indica una funcin que se ejecuta en la
GPU y se lanza desde la CPU. Por
mikernel<<<1,1>>>();
ejemplo, mikernel<<<1,1>>>.
printf("Hola mundo!\n");
return 0; Eso es todo lo que se requiere
} para ejecutar una funcin en GPU.
nvcc separa el cdigo fuente para la CPU y la GPU.
Las funciones que corresponden a la GPU (como
mikernel()) son procesadas por el compilador de Nvidia.
Las funciones de la CPU (como main()) son procesadas
por su compilador (gcc para Unix, cl.exe para Windows). 21
Hola mundo! con cdigo para la GPU (2/2)
__global__ void mikernel(void)
{ Salida:
}
$ nvcc hello.cu
int main(void) {
$ a.out
mikernel<<<1,1>>>();
Hola mundo!
$
printf("Hola mundo!\n");
return 0;
}
Versin de
Usuarios y rasgos ms sobresalientes
CUDA [ao]
1.0 [2007] Muchos investigadores y algunos usuarios madrugadores.
2.0 [2008] Cientficos y aplicaciones para computacin de altas prestaciones.
3.0 [2009] Lderes en la innovacin de aplicaciones.
4.0 [2011] Adopcin mucho ms extensa de desarrolladores.
5.0 [2012] Paralelismo dinmico, enlazado de objetos, Remote DMA.
6.0 [2014] Memoria unificada CPU-GPU
23
II. Arquitectura
II.1. El modelo hardware
de CUDA
Las generaciones hardware de CUDA
GFLOPS en doble precisin por cada vatio consumido
24
22
20 Pascal
Memoria 3D
18 NVLink
16
14
12 Maxwell
Memoria unificada
10 DX12
8
Kepler
6 Paralelismo dinmico
4
Fermi
2 Tesla FP64
CUDA
Multiprocesador N
Su banco de registros.
Memoria compartida. Multiprocesador 2
Multiprocesador 1
Una cach de constantes y otra
de texturas, ambas de slo Memoria compartida
GPU G80 (en torno a 600 MHz, frecuencia muy inferior a la de sus cores)
Multiprocesador 16
Multiprocesador 2
Multiprocesador 1 (los bloques de cdigo CUDA se mapean sobre los multipr.)
Memoria compartida (16 KB)
Multiprocesador 2
Multiprocesador 1 (los bloques de cdigo CUDA se mapean sobre los multipr.)
Memoria compartida (16 KB)
Memoria global (hasta 4 GB) (GDDR3, 512 bits @ 2x 1.1GHz = 141.7 GB/s)
31
Escalabilidad para futuras generaciones:
Alternativas para su crecimiento futuro
Aumentar el nmero de GPU
Multiprocesador 30
multiprocesadores por pares (escalabilidad en 1 gener.)
(nodo bsico), esto es, crecer Multiprocesador 2
en la dimensin Z. Es lo que Multiprocesador 1
hizo la 1 gener. (de 16 a 30). Memoria compartida
Aumentar el nmero de Registros Registros Registros
procesadores de cada
Core 1 Core 2 Core 8
multiprocesador, o crecer en la (escalabilidad en 2 y 3 gener.)
dimensin X. Es el camino
trazado por la 2 y 3 geners. Cach de texturas
Aumentar el tamao de la
memoria compartida, esto es, Memoria global
crecer en la dimensin Y. 32
II. 3. La segunda generacin:
Fermi (GF100)
El HW de Fermi comparado con los modelos
representativos de la generacin anterior
Arquitectura GPU G80 GT200 GF100 (Fermi)
Nombre comercial GeForce 8800 GTX 200 GTX 580
Ao de lanzamiento 2006 2008 2010
Nmero de transistores 681 millones 1400 millones 3000 millones
Nmero de cores (int y fp32) 128 240 512
Nmero de cores (fp64) 0 30 256
Velocidad de clculo en fp64 Ninguna 30 madds/ciclo 256 madds/ciclo
Planificadores de warps 1 1 2
Memoria compartida 16 KB 16 KB 16 KB + 48 KB
Cach L1 Ninguna Ninguna (o viceversa)
Cach L2 Ninguna Ninguna 768 KB
Correccin de errores
No No S
(DRAM)
Anchura del bus
32 bits 32 bits 64 bits
de direcciones
34
Arquitectura global de Fermi
35
Mejoras en la aritmtica
36
La jerarqua de memoria
13 37
II. 4. La tercera generacin:
Kepler (GK110)
Diagrama de bloques: Kepler GK110
7.100 Mt.
15 multiprocs. SMX.
> 1 TFLOP FP64.
Cach L2 de 1.5 MB.
GDDR5 de 384 bits.
PCI Express Gen3.
39
Escalabilidad de la arquitectura:
Sntesis de sus tres generaciones
Tesla Fermi Kepler
GeForce
GK104 GK110 GK110
Arquitectura G80 GT200 GF100 GF104 GTX
(K10) (K20) (K40)
Titan Z
Marco temporal 2006-07 2008-09 2010 2011 2012 2013 2013-14 2014
CUDA Compute
1.0 1.2 2.0 2.1 3.0 3.5 3.5 3.5
Capability (CCC)
N (multiprocs.) 16 30 16 7 8 14 15 30
Nmero de cores 128 240 512 336 1536 2688 2880 5760
40
La nueva GeForce GTX Titan Z
41
Evolucin de los multiprocesadores:
Del SM de Femi al SMX de Kepler
42
El multiprocesador SMX
Planificacin y emisin
de instrucciones en warps Front-end
Ejecucin de instrucciones.
512 unidades funcionales:
- 192 para aritmtica entera. Back-end
- 192 para aritmtica s.p.
- 64 para aritmtica d.p.
- 32 para carga/almacen.
- 32 para SFUs (log,sqrt, ...)
Incrementar ...
paralelismo
...
verticalmente
con ILP: ...
Si las instrs.
...
son ms
indepen- ...
dientes
... SMX 0
... La K40 puede
... ...... ejecutar hasta
... ...
... ... 512x15 = 7680
... ...... ...... hilos en un ciclo
... ...
... ...... ... ...... si stos son del
... ... ... ... color adecuado.
... ...... ...... ...... ......
... ... ... ... ...
... ... ... ... ...
... ... ... ... SMX 15
... ... ... ...
... ... ... ...
3:
... ...
da
... ...
...
to
...
s
...
(S
Recursos Carga/
ALU FPU 32 bits FPU 64 bits SFU
GPU almacen.
Fermi 32% 32% 16% 16% 4%
48
Cmo trabaja el front-end de la GPU:
(1) Planificacin de warps
53
El comportamiento de los warps nos ensea
que la GPU no es un procesador regular
Factores impredecibles en tiempo de ejecucin dificultan
un reparto equilibrado de la carga computacional entre los
multiprocesadores. Aqu vemos un ejemplo de la varianza
existente entre los 8 ltimos warps ejecutados en cada SM:
54
III. Programacin
El modelo de programacin CUDA
58
Conceptos bsicos
Multiprocesador N
Multiprocesador 2
Multiprocesador 1
Memoria compartida
de
Procesador 1 Procesador 2 Procesador M Control
SIMD
Cach para
constantes
Cach para
texturas
Memoria global
60
Recursos y limitaciones segn la GPU
que utilicemos para programar (CCC)
CUDA Compute Capability (CCC)
Limitacin Impacto
1.0, 1.1 1.2, 1.3 2.0, 2.1 3.0, 3.5
Lmite en Kepler: 1024 hilos por bloque, 2048 hilos por multiprocesador
Los bloques se
asignan a los
multiprocesadores
[Lmite en Kepler:
16 bloques
concurrentes por
Bloque 0 Bloque 1 Bloque 2
cada
multiprocesador]
Malla 0 [Lmite en Kepler: 4G bloques por malla]
Estos bloques
Tambin se dispone
de una memoria de
BR BR BR BR BR BR BR BR pueden
ejecutarse en
MLLocal memory:
ML ML Off-chip
ML ML ML ML ML un mismo
multiprocesador
Memoria compartida si se cumplen
ciertas
Memoria global: GDDR5 (DRAM) limitaciones de
espacio
Bloque 0 Bloque 1 Bloque 2
Significado: BR: Banco de registros. ML = Memoria local
Memoria GPU: On-chip Off-chip Malla 0
66
Pensando a lo grande: Particionamiento 1D
de un vector de 64 millones de elementos
Mximo nmero de hilos por bloque: 1K.
Maximo nmero de bloques:
64K en Fermi y 4G en Kepler.
Tamaos ms grandes para las estructuras de datos slo
pueden implementarse mediante un nmero ingente de
bloques (si queremos preservar el paralelismo fino).
Posibilidades a elegir:
64K bloques de 1K hilos cada uno.
128K bloques de 512 hilos cada uno (slo factible en Kepler).
256K bloques de 256 hilos cada uno (slo factible en Kepler).
... y as sucesivamente.
67
Recopilando sobre kernels,
bloques y paralelismo
Los kernels se lanzan en grids.
Malla
Un bloque se ejecuta en un
multiprocesador (SMX). Bloque (0, 0) Bloque (1, 0)
El bloque no migra.
Varios bloques pueden residir
concurrentemente en un SMX. Memoria compartida Memoria compartida
68
Escalabilidad transparente
Block 4 Block 5
Block 0 Block 1 Block 0 Block 1 Block 2 Block 3
Block 6 Block 7
}
y[i] = a*x[i] + y[i]; Cdigo C estndar
// Invocar al kernel SAXPY secuencial
saxpy_secuencial(n, 2.0, x, y);
81
Para gestionar la memoria de vdeo
84
Ejemplo 1: Implementacin
[cdigo C en rojo, extensiones CUDA en azul]
int main()
{
int N = 16;
int num_bytes = N*sizeof(int);
int *d_a=0, *h_a=0; // Punteros en dispos. (GPU) y host (CPU)
free(h_a);
cudaFree(d_a);
}
85
Transferencias de memoria asncronas
86
Ejemplo 2: Incrementar un valor b
a los N elementos de un vector
El kernel CUDA que se ejecuta en GPU,
Programa C en CPU.
seguido del cdigo host para CPU.
Este archivo se compila con gcc
Este archivo se compila con nvcc
__global__ void incremento_en_gpu(float *a, float b, int N)
void incremento_en_cpu(float *a, float b, int N) {
{ int idx = blockIdx.x * blockDim.x + threadIdx.x;
for (int idx = 0; idx<N; idx++) if (idx < N)
a[idx] = a[idx] + b; a[idx] = a[idx] + b;
} }
void main()
{
void main()
..
{
dim3 dimBlock (blocksize);
.....
dim3 dimGrid( ceil( N / (float)blocksize) );
incremento_en_cpu(a, b, N);
incremento_en_gpu<<<dimGrid, dimBlock>>>(a, b, N);
}
}
87
Ejemplo 2: Incrementar un valor b
a los N elementos de un vector
Nota: blockDim.x debera ser >= 32 (tamao del warp), esto es slo un ejemplo.
88
Cdigo en CPU para el ejemplo 2
[rojo es C, verde son variables, azul es CUDA]
// Aloja memoria en la CPU
unsigned int numBytes = N * sizeof(float);
float* h_A = (float*) malloc(numBytes);
void funcion_en_CPU( )
{
... Kernels Resto del
} CUDA cdigo C
void otras_funcs_CPU(int ...)
{
...
}
91
Los diferentes mdulos de compilacin
Aplicacin Cdigo
El cdigo fuente CUDA se CUDA C
fuente
compila con NVCC.
NVCC separa el cdigo que
se ejecuta en CPU del que lo NVCC Cdigo CPU
hace en GPU.
Virtual
La compilacin se realiza Cdigo PTX
en dos etapas:
Virtual: Genera cdigo PTX Fsica
(Parallel Thread eXecution). De PTX al com-
pilador destino
Fsica: Genera el binario para
una GPU especfica (o incluso
para una CPU multicore).
G80 GPU
Cdigo
objeto 92
Compilador nvcc y mquina virtual PTX
EDG
Separa cdigo GPU y CPU.
EDG Cdigo CPU Open64
Genera ensamblador PTX.
Parallel Thread eXecution (PTX)
Mquina virtual e ISA.
Open64
Modelo de programacin.
Recursos y estados de ejecucin.
Cdigo PTX
Proceso de
compilacin
en Windows:
94
Para conocer la utilizacin de los recursos
96
Heursticos (cont.)
98
CUDA Occupancy Calculator
99
Para alcanzar el mayor grado de paralelismo,
fijarse en el rea naranja del CUDA Occup.(1)
El primer dato es el nmero de hilos por bloque:
El lmite es 1024 en las generaciones Fermi y Kepler.
Las potencias de dos son las mejores elecciones.
Lista de candidatos: 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024.
Pondremos 256 como primera estimacin, y el ciclo de desarrollo nos
conducir al valor ptimo aqu, aunque normalmente:
Valores pequeos [2, 4, 8, 16] no explotan el tamao del warp ni los bancos de
memoria compartida.
Valores intermedios [32, 64] comprometen la cooperacin entre hilos y la
escalabilidad en Kepler, Maxwell y futuras generaciones de GPUs.
Valores grandes [512, 1024] nos impiden tener suficiente nmero de bloques
concurrentes en cada multiprocesador, ya que el mximo de hilos por bloque y SMX
son dos valores muy prximos. Adems, la cantidad de registros disponibles para
cada hilo es baja.
100
Para alcanzar el mayor grado de paralelismo,
fijarse en el rea naranja del CUDA Occup.(2)
El segundo dato es el n de registros que usa cada hilo.
Esto lo obtendremos del archivo .cubin.
El lmite es 8K (G80), 16K (GT200), 32K (Fermi), o 64K (Kepler),
as que consumiendo 10 registros/hilo es posible ejecutar:
En G80: 768 hilos/SM, o sea, 3 bloques de 256 hilos [3*256*10=7680] (< 8192).
En Kepler: Alcanzamos el mximo de 2048 hilos por SMX, aunque nos quedamos
muy cortos en el uso de los registros (podramos haber usado hasta 29 regs./hilo):
8 bloques * 256 hilos/bloque * 10 registros/hilo = 22480 regs. (< 65536 mx.).
En el caso de la G80, si hubiramos consumido 11 registros/hilo, ya
no podramos acomodar 3 bloques en el SMX, sino slo 2, por lo que
perderamos 1/3 del paralelismo => Habra que esforzarse en reducir
de 11 a 10 el nmero de registros.
101
Para alcanzar el mayor grado de paralelismo,
fijarse en el rea naranja del CUDA Occup.(3)
El tercer dato es el gasto de memoria compartida en cada
bloque de hilos:
Esto tambin lo obtenemos del archivo .cubin, aunque podemos
llevar una contabilidad manual, ya que todo depende de la declaracin
de variables __shared__ que elegimos como programador.
Lmites: 16 KB (CCC 1.x), 16/48 KB (CCC 2.x), 16/32/48 KB (3.x).
Para el caso anterior sobre la G80, no gastaremos ms de 5 KB de
memoria compartida por cada bloque para que podamos ejecutar el
mximo de 3 bloques en paralelo en cada multiprocesador:
3 bloques x 5 KB./bloque = 15 KB (< 16 KB.)
A partir de 5.33 KB. de memoria compartida usada por cada bloque,
estamos sacrificando un 33% del paralelismo, igual que suceda antes
si no ramos capaces de bajar a 10 registros/kernel.
102
VI. Ejemplos: VectorAdd, Stencil,
ReverseArray, MxM
Pasos para la construccin del cdigo CUDA
104
Se requiere cierta coordinacin
en las tareas paralelas
El paralelismo viene expresado por los bloques e hilos.
Los hilos de un bloque pueden requerir sincronizacin si
aparecen dependencias, ya que slo dentro del warp se
garantiza su progresin conjunta (SIMD). Ejemplo:
a[i] = b[i] + 7;
syncthreads();
x[i] = a[i-1]; // El warp 1 lee aqu el valor a[31],
// que debe haber sido escrito ANTES por el warp 0
111
VI. 2. Kernels patrn (stencils)
Por qu hemos seleccionado este cdigo
113
Patrn unidimensional (1D)
radio radio
De nuevo aplicamos paralelismo de grano fino, por lo que
cada hilo se encargar de obtener el resultado de un solo
elemento del vector resultado.
Los valores del vector de entrada deben leerse varias veces:
Por ejemplo, para un radio de 3, cada elemento se leer 7 veces. 114
Compartiendo datos entre hilos. Ventajas
Usar __synchthreads();
__global__ void stencil_1d(...) {
para sincronizar todos los hilos de
un bloque: < Declarar variables e ndices>
La barrera tiene que ser alcanzada < Pasar el vector a mem. compartida >
por todos los hilos antes de que stos
puedan continuar. __synchthreads();
Puede utilizarse para prevenir < Aplicar el patrn >
riesgos del tipo RAW / WAR / WAW.
En sentencias condicionales, la < Almacenar el resultado >
codicin debe ser uniforme a lo largo
}
de todo el bloque.
119
Recopilando los conceptos puestos
en prctica en este ejemplo
Lanzar N bloques con M hilos por bloque para ejecutar los hilos
en paralelo. Emplear:
kernel<<<N,M>>>();
Acceder al ndice del bloque dentro de la malla y al ndice del hilo
dentro del bloque. Emplear:
blockIdx.x y threadIdx.x;
Calcular los ndices globales donde cada hilo tenga que trabajar
en un rea de datos diferente segn la particin. Emplear:
int index = threadIdx.x + blockIdx.x * blockDim.x;
Declarar el vector en memoria compartida. Emplear:
__shared__ (como prefijo antecediendo al tipo de dato en la declaracin).
Sincronizar los hilos para prevenir los riesgos de datos. Emplear:
__synchthreads(); 120
VI. 3. Invertir el orden a
los elementos de un vector
Cdigo en GPU para el kernel ReverseArray
(1) utilizando un nico bloque
__global__ void reverseArray(int *in, int *out) {
int index_in = threadIdx.x;
int index_out = blockDim.x 1 threadIdx.x;
122
Cdigo en GPU para el kernel ReverseArray
(2) con mltiples bloques
__global__ void reverseArray(int *in, int *out) {
int in_offset = blockIdx.x * blockDim.x;
int out_offset = (gridDim.x 1 blockIdx.x) * blockDim.x;
int index_in = in_offset + threadIdx.x;
int index_out = out_offset + (blockDim.x 1 threadIdx.x);
123
Versin utilizando la memoria compartida
124
Cdigo en GPU para el kernel ReverseArray
(3) con mltiples bloques y mem. compartida
__global__ void reverseArray(int *in, int *out) {
__shared__ int temp[BLOCK_SIZE];
int gindex = threadIdx.x + blockIdx.x * blockDim.x;
int lindex = threadIdx.x;
125
VI. 4. Producto de matrices
Versin de cdigo CPU escrita en lenguaje C
B
C = A * B.
Matrices cuadradas de tamao N * N.
Linearizadas en vectores para simplificar
el alojamiento de memoria dinmica.
void MxMonCPU(float* A, float* B, float* C, int N);
{
for (int i=0; i<N; i++)
for (int j=0; j<N; j++) A C
{
float sum=0;
for (int k=0; k<N; k++)
{
float a = A[i*N + k];
N
float b = B[k*N + j];
sum += a*b;
}
C[i*N + j] = sum;
} N N
} 127
Versin CUDA para el producto de matrices:
Un primer borrador para el cdigo paralelo
B
__global__ MxMonGPU(float* A, float* B, float* C, int N);
{
float sum=0;
int i, j;
i = threadIdx.x + blockIdx.x * blockDim.x;
j = threadIdx.y + blockIdx.y * blockDim.y;
for (int k=0; k<N; k++)
{
float a = A[i*N + k];
float b = B[k*N + j];
sum += a*b; A C
}
C[i*N + j] = sum;
}
N
N N
128
Versin CUDA para el producto de matrices:
Descripcin de la paralelizacin
Cada hilo computa un elemento de la matriz resultado C.
Las matrices A y B se cargan N veces desde memoria de vdeo.
Los bloques acomodan los hilos en grupos de 1024
N
(limitacin interna en arquitecturas Fermi y Kepler).
As podemos usar bloques 2D de 32x32 hilos cada uno.
Anchura B Anchura A Anchura B
Malla
Bloque
Altura B
Altura A
Altura A
= X
C(x, y)
N
C A B
dim2 dimBlock(BLOCKSIZE, BLOCKSIZE);
Hilo(x,y)
dim2 dimGrid(AnchuraB/BLOCKSIZE, AlturaA/BLOCKSIZE);
...
N
MxMonGPU <<<dimGrid,dimBlock>>> (A, B,N C, N);
129
Versin CUDA para el producto de matrices:
Anlisis
Cada hilo utiliza 10 registros, lo que nos permite alcanzar
el mayor grado de paralelismo en Kepler:
2 bloques de 1024 hilos (32x32) en cada SMX. [2x1024x10 =
20480 registros, que es inferior a la cota de 65536 regs. disponibles].
Problemas:
Baja intensidad aritmtica.
Exigente en el ancho de banda a memoria, que termina erigindose
como el cuello de botella para el rendimiento.
Solucin:
Utilizar la memoria compartida de cada multiprocesador.
130
Utilizando la memoria compartida:
Versin con mosaicos (tiling)
B
La submatriz de Csub de 32x32 datos
M
computada por cada bloque de hilos
utiliza mosaicos de 32x32 elementos de A
N
y B que se alojan de forma reiterativa en
memoria compartida.
M
A y B se cargan slo (N/32) veces
desde memoria global. A C
Logros:
Menos exigente en el Csub
N
Ms intensidad aritmtica.
M M M M
N N
131
Tiling: Detalles de la implementacin
134
Una optimizacin gracias al compilador:
Desenrrollado de bucles (loop unrolling)
Sin desenrrollar el bucle: Desenrrollando el bucle:
... ...
__syncthreads(); __syncthreads();
sum += As[tx][31]*Bs[31][ty];
__syncthreads();
}
C[indexC] = sum;
135
Rendimiento con tiling & unrolling en la G80
100
75
GFLOPS
50
25
Slo tiling
Tiling & Unrolling
0
4x4 8x8 12x12 16x16
Tamao del mosaico (32x32 no es factible en la G80)
136
VII. Bibliografa y herramientas
CUDA Zone:
La web bsica del programador CUDA
- Compilador (NVCC).
- Depurador (GDB).
- Profiler (cudaprof y Visual).
- Entorno de desarrollo (Nsight).
- Cdigos de ejemplo.
- Eclipse.
- Matlab.
- CUDA Fortran.
- GPUDirect.
- SDK para el compilador LLVM.
[developer.nvidia.com/cuda-zone] 138
CUDA 6 Production Release. Descarga gratis
para todas las plataformas y usuarios
[developer.nvidia.com/cuda-downloads]
139
Libros sobre CUDA: Desde 2007 hasta 2013
142
Cursos on-line de acceso gratuito
143
Tutoriales cortos sobre
C/C++, Fortran y Python
Hay que registrarse en la Web de los tutoriales que hay
dados de alta en los servicios en la nube de Amazon EC2:
[nvidia.qwiklab.com]
Suelen ser sesiones de 90 minutos.
Slo se necesita un navegador de Web y una conexin SSH.
Algunos tutoriales son gratuitos, otros requieren tokens de $29.99.
144
Charlas y webinarios
145
Ejemplos de webinarios sobre CUDA 6.0
146
Desarrolladores
148
Tendencias futuras
150