+ All Categories
Home > Documents > CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un...

CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un...

Date post: 13-Aug-2020
Category:
Upload: others
View: 2 times
Download: 0 times
Share this document with a friend
23
Departamento de Ciencias de la computación Universidad de Chile Modelado en 3D y sus Aplicaciones en Realidad Virtual CC68W CUDA Overview and Programming model Student: Juan Silva Professor: Dr. Wolfram Luther Date: lunes, 22 de noviembre de 2010
Transcript
Page 1: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

Departamento de Ciencias de la computación Universidad de Chile

Modelado en 3D y sus Aplicaciones en Realidad Virtual

CC68W

CUDA Overview and Programming

model

Student: Juan Silva

Professor: Dr. Wolfram Luther Date: lunes, 22 de noviembre de 2010

Page 2: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

1

Contents

Abstract ............................................................................................................................................... 3

Introducción ........................................................................................................................................ 3

Requerimientos ................................................................................................................................... 4

Conceptos generales ........................................................................................................................... 5

Objetivos de CUDA .......................................................................................................................... 5

Conceptos de programación ........................................................................................................... 5

Device .......................................................................................................................................... 5

Host ............................................................................................................................................. 5

Kernel .......................................................................................................................................... 5

CUDA Threads ............................................................................................................................. 6

Modelo de programación .................................................................................................................... 8

Modelo de memoria ........................................................................................................................ 8

Registros ...................................................................................................................................... 8

Memoria local ............................................................................................................................. 8

Memoria compartida .................................................................................................................. 8

Memoria global (Dispositivo) ...................................................................................................... 8

Memoria Host (CPU) ................................................................................................................... 9

Runtime API y Driver API: .............................................................................................................. 10

Driver API................................................................................................................................... 10

Runtime API ............................................................................................................................... 10

Manejo de memoria ...................................................................................................................... 11

Alocar memoria en el dispositivo .............................................................................................. 11

Establecer valores de memoria en el dispositivo ...................................................................... 11

Page 3: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

2

Liberar memoria del dispositivo ................................................................................................ 12

Copia de datos ........................................................................................................................... 13

Ejecución de código en GPU .......................................................................................................... 14

Calificadores de función ............................................................................................................ 14

Ejecutando Kernel ..................................................................................................................... 15

Descomposición de los datos .................................................................................................... 16

Kernels de ejemplo .................................................................................................................... 16

Ejemplo de código ......................................................................................................................... 17

Sincronización ........................................................................................................................... 17

Proyecto ............................................................................................................................................ 18

Sistema usado para este proyecto ................................................................................................ 18

Entorno de trabajo ........................................................................................................................ 19

Problemas en la implantación del entorno de trabajo ................................................................. 19

Resultados de la comparación ...................................................................................................... 20

Conclusiones del proyecto ............................................................................................................ 21

Conclusiones generales ..................................................................................................................... 21

Referencias ........................................................................................................................................ 22

Page 4: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

3

Abstract

El poder de procesamiento de hoy en día se basa en el uso de múltiples núcleos en un solo

procesador para aumentar el rendimiento y poder de cómputo, sin embargo, estos procesadores

involucran un gran costo debido a la tecnología involucrada, pues además del procesador, hay que

comprar memorias y placa madre compatible con el procesador por lo que se podría decir que son

poco escalables, por otro lado están las tarjetas de video que pueden funcionar bajo la mayoría de

los computadores actuales sin restricciones como procesador o placa madre, además estas

cuentan con múltiples procesadores pudiendo procesar miles de threads de forma paralela, otra

ventaja es que varias tarjetas de video pueden trabajar juntas en un solo computador y pueden

ser reemplazadas fácilmente. Es por este motivo que se crea CUDA, con el fin de aprovechar el

poder de cómputo de las tarjetas de video, teniendo una plataforma de cómputo extensible,

potente y de fácil uso.

Introducción

CUDA es el acrónimo para Compute Unified Device Architecture el cual es una arquitectura de

cómputo desarrollada por NVIDIA. CUDA es el motor de computo en unidades de procesamiento

graficas (GPUs) de NVIDIA el cual es accesible para programadores de software mediante variantes

de lenguajes de programación estándar. Los desarrolladores de software pueden usar C para

CUDA, el cual es el lenguaje de programación C con extensiones provistas por NVIDIA y con ciertas

restricciones, y compilar el código mediante un compilador escalable Open64 C para luego ser

ejecutado en tarjetas de video NVIDIA1.

CUDA aprovecha las ventajas de las tarjetas de video NVIDIA para procesar elementos dentro de

múltiples procesadores con miles de threads concurrentes, facilitando el uso y facilidad de

programación. NVIDIA apoyando y alentando la adopción de esta tecnología, ha sacado al

mercado varios servidores de cómputo llamados TESLA orientados a estaciones de trabajo para

Clusters y también para gran escala para Data Center, siendo estos promocionados por tener un

rendimiento comparable con el ultimo procesador quad-core del mercado consumiendo 1/20 de

energía y a un 1/10 del costo2.

En este trabajo se abordara el cómo programar sobre la plataforma CUDA, usando el sistema

operativo Windows 7 Profesional versión 64bits con Microsoft Visual Studio 2008 Profesional. Se

presentarán los problemas encontrados y las soluciones provistas para luego presentar el proyecto

de ejemplo desarrollado en CUDA.

1 http://en.wikipedia.org/wiki/CUDA

2 http://www.nvidia.com/object/tesla_computing_solutions.html

Page 5: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

4

Requerimientos

Para desarrollar con tecnología CUDA es necesario conocer el sistema en el cual se está trabajando

y el sistema objetivo a desarrollar, estos puntos son importantes ya que el kit de desarrollo de

CUDA no implementa un sistema multi-plataformas por lo que es necesario descargar o compilar

las bibliotecas necesarias para determinado sistema. A continuación se presentan los

requerimientos mínimos para desarrollar sobre Sistema operativo Windows3.

Sistema operativo: Windows XP/Vista/7 32/64 bits.

IDE Recomendado: Microsoft Visual Studio 2005 o superior.

NVIDIA Driver para correr aplicaciones en CUDA.

CUDA Toolkit 32/64 bits.

Hardware recomendado:

NVIDIA GeForce 8 series o superior.

Cabe destacar que CUDA Toolkit trae un emulador incorporado en donde mediante las opciones

de preferencias, se puede ejecutar el código de GPU en la CPU del equipo, evitando tener que

forzadamente comprar una tarjeta de video para el desarrollo.

3 http://developer.nvidia.com/object/cuda_3_2_downloads.html

Page 6: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

5

Conceptos generales

En esta sección se trataran los conceptos generales sobre CUDA, sus modelos de programación y

modelos de memoria4.

Objetivos de CUDA

Los objetivos de CUDA se basan en la escalabilidad que presentan las tarjetas gráficas de NVIDIA

donde escalan mediante el aumento de multiprocesadores con múltiples núcleos de trabajo lo

cual logra un total de núcleos de procesamiento del orden de y donde cada núcleo de

procesamiento puede trabajar cientos de threads lo cual genera del orden de de threads

para poder procesar datos. Otro punto considerado como objetivo es poder ofrecer de manera

sencilla y fácil de usar el poder de procesamiento y para esto se desea facilitar la computación

heterogenea de CPU + GPU.

Conceptos de programación

CUDA introduce varios conceptos de programación asociados a su arquitectura dentro de los

cuales se distinguen el Device, Host y Kernel.

Device

A la unidad de procesamiento grafica o GPU se le llama Device o dispositivo, pueden haber tantos

dispositivos como tarjetas de video tenga el computador distinguiéndose cada una por un

identificador, nombre y poder de computo.

Host

A la unidad central de procesamiento se le denomina Host, es en el Host donde se ejecuta

cualquier código deseado por el programado, sin restricciones y como complemento al código

ejecutado por el dispositivo.

Kernel

Los Kernel son fragmentos de código que se ejecutaran en paralelo dentro del dispositivo. Solo un

kernel es ejecutado a la vez y muchos threads son ejecutados por cada kernel. La principal

diferencia entre los threads de CUDA y los de CPU son que los threads de CUDA son

extremadamente ligeros, requieren un gasto de recursos muy pequeños para su creación y

pueden ser conmutados rápidamente, otro punto es que CUDA ocupa miles de threads para

obtener eficiencia mientras que CPUs de múltiples núcleos solo pueden usar unos pocos.

4 San Diego Supercomputer Center > Training > NVIDIA CUDA Workshop > Basic of CUDA.

http://www.sdsc.edu/us/training/workshops.php?status=past

Page 7: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

6

CUDA Threads

Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo

código y se diferencian por un identificador o threadID el cual se usa para procesar direcciones de

memoria y tomar decisiones de control.

Ilustración 1: CUDA thread array.

Un kernel lanza una cuadricula de bloques de thread, threads dentro de un bloque cooperan via

memoria compartida o shared memory, threads dentro de diferentes bloques no pueden cooperar

entre sí. Esta característica deja a los desarrolladores escalar transparentemente mediante

diferentes GPUs.

threadID

float x = input[threadID];

float y = func(x);

output[threadID] = y;

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8

Bloque thread 0

Memoria compartida

Bloque thread 1

Memoria compartida

Bloque thread 2

Memoria compartida

...

...

Bloque thread n

Memoria compartida

Cuadricula

Ilustración 2: Cuadricula de bloques de threads.

Page 8: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

7

Cada bloque y cada thread pueden tener más de una dimensión. Un ID de bloque puede tener 1 y

2 dimensiones y cada ID de thread puede tener 1, 2 y 3 dimensiones como se muestra en la

ilustración 7. Esto simplifica el acceso a memoria cuando se procesan datos multidimensionales.

Ilustración 3: Dimensiones de cuadricula, bloques y threads.

Dispositivo

Cuadricula

Bloque (0,0)

Bloque

(1,0)

Bloque

(2,0)

Bloque

(0,1)

Bloque

(1,1)

Bloque

(2,1)

Bloque (1,0)

Thread (0,0,0)

Thread

(1,0,0)

Thread

(2,0,0)

Thread

(3,0,0)

Thread

(0,1,0)

Thread

(1,1,0)

Thread

(2,1,0)

Thread

(3,1,0)

Thread

(0,2,0)

Thread

(1,2,0)

Thread

(2,2,0)

Thread

(3,2,0)

Thread

(0,3,0)

Thread

(1,3,0)

Thread

(2,3,0)

Thread

(3,3,0)

Thread

(0,0,1)

Thread

(1,0,1)

Thread

(2,0,1)

Thread

(3,0,1)

Thread

(0,1,1)

Thread

(1,1,1)

Thread

(2,1,1)

Thread

(3,1,1)

Thread

(0,2,1)

Thread

(1,2,1)

Thread

(2,2,1)

Thread

(3,2,1)

Thread

(0,3,1)

Thread

(1,3,1)

Thread

(2,3,1)

Thread

(3,3,1)

Page 9: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

8

Modelo de programación

CUDA establece un modelo de programación basado en la idea de Kernel, cuadricula o Grid,

Bloques y threads. Un kernel es ejecutado por una cuadricula la cual contiene varios bloques,

estos bloques son un conjunto de threads que pueden cooperar entre si compartiendo datos vía

memoria compartida y sincronizando su ejecución. Threads de diferentes bloques no pueden

cooperar entre si. Este punto es importante pues dependiendo de la complejidad del problema es

que pueden ser de utilidad pocos bloques de gran tamaño o varios bloques de tamaño pequeño.

Modelo de memoria

CUDA establece acorde a la arquitectura de la GPU varios modelos de memoria y cada uno con un

propósito y un fin distinto.

Registros

Los registros son los elementos más pequeños dentro de la arquitectura, estos registros se asignan

por thread y tienen un ciclo de vida igual al thread.

Memoria local

Al igual que los registros, la memoria local es asignada a cada thread y respetan el ciclo de vida del

mismo, sin embargo este tipo de memoria se encuentra físicamente en la memoria DRAM del

dispositivo.

Memoria compartida

La memoria compartida es asignada a cada bloque de threads y se encuentra físicamente en la

tarjeta de video. Esta memoria tiene un ciclo de vida igual al ciclo de un bloque.

Memoria global (Dispositivo)

Esta memoria es accesible por todos los threads al igual que el Host, la vida útil de este tipo de

memoria respeta los alocamientos y de alocamientos de memoria y es controlado por el

programador.

Page 10: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

9

Memoria Host (CPU)

La memoria del host respeta los alocamientos y de alocamientos y no es accesible por los threads

de CUDA.

Ilustración 4: Modelo de memoria en CUDA.

Bloque 0 Bloque 1 Bloque 2 … Bloque n

Kernel 0 Mem

oria G

lob

al

Bloque 0 Bloque 1 Bloque 2 … Bloque n

Kernel 1

Registro

Memoria

local

Bloque 0

Memoria

compartida

Page 11: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

10

Runtime API y Driver API:

Existen dos interfaces de programación de aplicaciones (API).

Driver API

La de más bajo nivel es la llamada Driver API la cual contiene funciones con prefijo esta

API tiene varias ventajas, dentro de las cuales se encuentran:

No depende de bibliotecas de tiempo de ejecución o runtime library.

Posee más control sobre los dispositivos pudiendo, un thread de CPU, controlar múltiples

GPUs.

No existen extensiones C en el código del host, pudiendo asi usar cualquier otro

compilador de CPU del por defecto en el Host( ejemplo: icc, etc…)

Posibilita el uso de Parallel Thread eXecution (PTX) Just-in-Time (JIT) compilation.

Runtime API

La API de más alto nivel es la llamada Runtime API la cual contiene funciones con prefijo

esta API también tiene ventajas, dentro de las cuales se encuentran:

Facilita el manejo por código del dispositivo proveyendo inicialización implícita.

Provee manejo de contextos y manejo de módulos.

Más fácil de utilizar que Driver API.

Todo el código del dispositivo es idéntico usando una u otra API.

Por razones de simplicidad se explicara el uso de Runtime API.

Page 12: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

11

Manejo de memoria5

Lo primero que hay que tener en cuenta es que tanto la memoria de uso de CPU y GPU tienen

distintos espacios. Lo segundo es que la memoria del dispositivo es manejada mediante código

desde el Host. El host puede alocar y liberar memoria, copiar datos hacia y desde el dispositivo y

administrar la memoria global del dispositivo.

Alocar memoria en el dispositivo

Alocar memoria en el dispositivo permite trabajar con datos y esto se realiza mediante la función:

Esta función asigna a pointer la dirección de memoria alocada y aloca un tamaño de memoria

dictado por nbytes. Devuelve un código de error dictado por cudaError_t de existir alguno. Existen

variantes de esta función las cuales son:

Establecer valores de memoria en el dispositivo

Establecer valores en memoria del dispositivo se realiza mediante la función:

Esta función recibe como parámetro una dirección de memoria en el dispositivo referenciada por

pointer, asigna los primeros count valores de la dirección de memoria el valor value. Otras

funciones similares son:

5 http://developer.download.nvidia.com/compute/cuda/3_2/toolkit/docs/online/group__CUDART__MEMORY.html

𝒄𝒖𝒅𝒂𝑬𝒓𝒓𝒐𝒓_𝒕 𝒄𝒖𝒅𝒂𝑴𝒂𝒍𝒍𝒐𝒄 𝒗𝒐𝒊𝒅 𝒑𝒐𝒊𝒏𝒕𝒆𝒓, 𝒔𝒊𝒛𝒆_𝒕 𝒏𝒃𝒚𝒕𝒆𝒔

cudaMalloc3D, cudaMalloc3DArray, cudaMallocArray, cudaMallocHost y cudaMallocPitch.

𝒄𝒖𝒅𝒂𝑴𝒆𝒎𝒔𝒆𝒕 𝒗𝒐𝒊𝒅 𝒑𝒐𝒊𝒏𝒕𝒆𝒓, 𝒊𝒏𝒕 𝒗𝒂𝒍𝒖𝒆, 𝒔𝒊𝒛𝒆_𝒕 𝒄𝒐𝒖𝒏𝒕

cudaMemsetAsync, cudaMemset2D, cudaMemset2DAsync, cudaMemset3D y

cudaMemset3DAsync.

Page 13: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

12

Liberar memoria del dispositivo

Liberar memoria permite reutilizar espacios de memoria para un posterior uso, esto se realiza

mediante la función:

Esta función recibe como parámetro una dirección de memoria en el dispositivo referenciada por

pointer para luego liberar la memoria del espacio indicado. Otras funciones similares son:

Ejemplo de manejo de memoria

𝒄𝒖𝒅𝒂𝑭𝒓𝒆𝒆 𝒗𝒐𝒊𝒅 𝒅𝒆𝒗𝑷𝒕𝒓

cudaFreeArray y cudaFreeHost.

int total_ints = 1024; int nbytes = total_ints*sizeof(int); int *device_allocation = 0; // Aloca nbytes en memoria y retorna la dirección mediante device_allocation cudaMalloc( (void**) &device_allocation, nbytes ); // Establece en 0 todos los valores del espacio de memoria device_allocation cudaMemset( device_allocation, 0, nbytes ); // Libera el espacio de memoria utilizado cudaFree( device_allocation );

Page 14: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

13

Copia de datos

Copiar datos permite rescatar resultados o pasar parámetros para el posterior uso, esto se realiza

mediante la función:

Esta función copia los count primeros bytes del área de memoria apuntada por src al espacio de

memoria apuntado por dst en la dirección que indique kind la cual puede ser:

cudaMemcpyHostToDevice: copia desde el Host al dispositivo.

cudaMemcpyDeviceToHost: copia desde el dispositivo al Host.

cudaMemcpyDeviceToDevice: copia desde un Dispositivo a otro Dispositivo.

Otras funciones similares son:

𝒄𝒖𝒅𝒂𝑴𝒆𝒎𝒄𝒑𝒚 𝒗𝒐𝒊𝒅 𝒅𝒔𝒕, 𝒄𝒐𝒏𝒔𝒕 𝒗𝒐𝒊𝒅 𝒔𝒓𝒄 , 𝒔𝒊𝒛𝒆_𝒕 𝒄𝒐𝒖𝒏𝒕,

𝒆𝒏𝒖𝒎 𝒄𝒖𝒅𝒂𝑴𝒆𝒎𝒄𝒐𝒑𝒚𝑲𝒊𝒏𝒅 𝒌𝒊𝒏𝒅

cudaMemcpy2D, cudaMemcpy2DArrayToArray, cudaMemcpy2DAsync,

cudaMemcpy2DFromArray, cudaMemcpy2DFromArrayAsync, cudaMemcpy2DToArray,

cudaMemcpy2DToArrayAsync, cudaMemcpy3D, cudaMemcpy3DAsync,

cudaMemcpyArrayToArray, cudaMemcpyAsync, cudaMemcpyFromArray,

cudaMemcpyFromArrayAsync, cudaMemcpyFromSymbol, cudaMemcpyFromSymbolAsync,

cudaMemcpyToArray, cudaMemcpyToArrayAsync, cudaMemcpyToSymbol y

cudaMemcpyToSymbolAsync.

Page 15: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

14

Ejecución de código en GPU

Los Kernel son funciones en C con algunas restricciones, estas restricciones son:

Solo se puede acceder a memoria de GPU.

Debe tener retorno de tipo void.

No se aceptan argumentos variables ( varargs ).

No se acepta recursión.

No se aceptan variables estáticas.

Los argumentos de la llamada a función son automáticamente copiados desde la memoria de la

CPU a la memoria de la GPU.

Calificadores de función

Los Kernel deben establecer una calificación de la función que representa desde donde se puede

invocar la función. Así estos calificadores son los siguientes:

__global__ : Este tipo de función se invocan desde el interior del código del host y no

pueden ser llamados desde el código del dispositivo y solo pueden retornar void.

__device__ : Este tipo de función puede ser llamado desde otras funciones dentro del

código del dispositivo y no pueden ser llamadas dentro del código del host.

__host__ : Solo pueden ser ejecutadas y llamadas dentro del host.

Los calificadores __host__ y __device__ pueden ser combinados usando sobrecargas de función y

el compilador generara código tanto para CPU como para GPU.

Page 16: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

15

Ejecutando Kernel

La sintaxis de ejecución de un kernel tiene en cuenta los parámetros de configuración de la

ejecución en el dispositivo dando así la siguiente sintaxis.

Kernel es la función que se ejecutara dentro del dispositivo, dim3 grid son las dimensiones de la

cuadricula de ejecución (medidas en bloques) la cual puede tener 1 o 2 dimensiones, dim3 block

son las dimensiones de cada bloque (medidas en threads) dentro de la cuadricula y puede tener 1,

2 o 3 dimensiones y args son los parámetros de ejecución de la función kernel. Así la ejecución de

un kernel se puede expresar como:

Todos los kernel calificados como __global__ y __device__ tienen acceso a las siguientes variables

definidas automáticamente.

dim3 gridDim: representa las dimensiones de la cuadricula en bloques.

dim3 blockDim: representa las dimensiones del bloque en threads.

dim3 blockIdx: representa el índice del bloque dentro de la cuadricula.

dim3 threadIdx: representa el índice del thread dentro del bloque.

𝒌𝒆𝒓𝒏𝒆𝒍 <<< 𝒅𝒊𝒎𝟑 𝒈𝒓𝒊𝒅,𝒅𝒊𝒎𝟑 𝒃𝒍𝒐𝒄𝒌 >>> 𝒂𝒓𝒈𝒔

dim3 grid(65535, 65535); dim3 block(512, 512, 64); // Llama a la funcion kernel para ser ejecutada en el dispositivo, devuelve inmediatamente. kernel <<<grid, block>>>(args);

Page 17: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

16

Descomposición de los datos

Generalmente se querrá que cada thread dentro de un kernel acceda a diferentes elementos

dentro de un arreglo de datos. Es así como se presenta un ejemplo de la descomposición de los

datos dentro de un kernel.

Ilustración 5: Modelo de descomposición de datos.

Kernels de ejemplo

Algunos ejemplos de kernels sencillos se presentan a continuación:

Cabe destacar que la penúltima línea de código, donde se declara la variable idx sigue un patrón

común dentro de los desarrollos y es debido al acceso a datos dentro de un arreglo mediante cada

thread, así cada thread accede a un solo dato dentro de un arreglo.

blockIdx.x

blockDim.x = 5

threadIdx.x

blockIdx.x * blockDimx

+ threadIdx.x

Grid

Block 0

0 1 2 3 4

Block 1

0 1 2 3 4

Block 2

0 1 2 3 4

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14

__global__ void kernel_set( int* d_a) { *d_a = 13; } // Asigna a cada elemento del arreglo el valor designado por value __global__ void assing( int* d_a, int value) { Int idx = blockDim.x * blockIdx.x + threadIdx.x; d_a[idx] = value; }

Page 18: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

17

Ejemplo de código A continuación se presenta un ejemplo de código que suma una constante a cada elemento de un

arreglo, se presenta el código de CPU y el código en CUDA.

Programa en CPU Programa en CUDA

void increment_cpu(float *a, float b, int N) { for(int idx = 0; idx < N; idx ++) a[idx] = a[idx] + b; } … void main() { … increment_cpu(a, b, N); }

__gloabl__ void increment_gpu(float *a, float b, int N) { int idx = blockIdx.x * blockDim.x + threadIdx.x; if( idx < N) a[idx] = a[idx] + b; } … void main() { dim3 dimBlock(blocksize); dim3 dimGrid(ceil( N/ (float) blocksize)); Increment_gpu <<< dimGrid, dimBlock >>> (a, b, N); }

Sincronización

Todas las llamadas a kernel son asíncronas, por lo que estas devuelven el control a la CPU de

inmediato, además la llamada a kernel se ejecuta después de haber terminado todas las llamadas

previas de CUDA. Este punto es importante para el correcto acceso a datos, para esto CUDA

maneja una serie de funciones para poder sincronizar el código y dentro de estas la más útil y

simple de usar es la llamada a la siguiente función:

Esta función genera un bloqueo hasta que el dispositivo ha completado todas las operaciones

anteriores.

𝒄𝒖𝒅𝒂𝑻𝒉𝒓𝒆𝒂𝒅𝑺𝒚𝒏𝒄𝒉𝒓𝒐𝒏𝒊𝒛𝒆 𝒗𝒐𝒊𝒅

Page 19: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

18

Proyecto El proyecto de presentación consistió en la implantación del entorno de trabajo y el desarrollo de

una comparación de tiempo entre CPU y GPU de cálculo de cuadraturas presentando previamente

la información del dispositivo.

Sistema usado para este proyecto A continuación se describe en detalle el sistema ocupado para el desarrollo del proyecto

Sistema operativo: Windows Vista 7 Professional 64bits.

IDE: Microsoft Visual Studio 2008 Professional.

CUDA Toolkit 64bits versión 3.2.

NVIDIA GeForce GTX 275 (Ver ilustración 1).

Procesador Intel Core i5 – 750 (Ver ilustración 2).

4GB Ram DDR3.

Ilustración 6: Detalle de tarjeta de video.

Ilustración 7: Detalle de CPU

Page 20: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

19

Entorno de trabajo

Para empezar a desarrollar es recomendado tener instalado un entorno integrado de desarrollo,

con esto en mente se recomienda instalar Microsoft Visual Studio 2008. Luego es necesario

instalar el kit de desarrollo CUDA Toolkit 3.26 (ver ilustración 3).

Una vez instalado el Toolkit, se procede a instalar los proyectos de ejemplo llamados GPU

Computing SDK code samples7 (ver ilustración 4).

Ilustración 8: NVIDIA CUDA Toolkit installer.

Ilustración 9: GPU Computing SDK code samples installer.

Una vez instalados estos elementos se tiene un ambiente listo para desarrollar en CUDA.

Problemas en la implantación del entorno de trabajo Debido las distinciones entre sistemas operativos de 32 y 64 bits, el montaje del entorno de

trabajo para 64 bits es complicado, la causa principal de esto es que los archivos de ejemplo

vienen con una configuración para entornos de trabajo de 32 bits y los archivos de configuración

no se encuentran debidamente escritos por lo que se debió recurrir a ayuda desde internet donde

se planteaban los mismos problemas. Además, al instalar todos los elementos recomendados y los

ejemplos existían conflictos por los archivos descriptores de compilación de código CUDA (*.rule)

que no se encontraban en el lugar que deberían por lo que se debió copiar a la ruta indicada.

6 http://www.nvidia.com/object/thankyou.html?url=/compute/cuda/3_2_prod/toolkit/cudatoolkit_3.2.16_win_64.msi

7 http://developer.download.nvidia.com/compute/cuda/3_2_prod/sdk/gpucomputingsdk_3.2.16_win_64.exe

Page 21: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

20

Resultados de la comparación Una vez implementada la comparación, se precedió a ejecutar el código y registrar los datos. La

ejecución del código contemplo una iteración de 200 datos incrementales, estos datos fueron

generados al azar mediante la función rand() iniciando con un tamaño de 1 llegando a un tamaño

de 8.000.000. Primeramente se procedió a calcular la cuadratura de cada número dentro del

arreglo mediante GPU para luego medir el tiempo de cálculo mediante CPU de forma iterativa.

Los resultados de esta ejecución se muestran a continuación:

Ilustración 10: Tabla comparativa de tiempos de procesamiento de datos.

0,0001

0,001

0,01

0,1

1

10

100

1

51

2

33

75

10

64

8

24

38

9

46

65

6

79

50

7

12

50

00

18

51

93

26

21

44

35

79

11

47

45

52

61

41

25

77

86

88

97

02

99

11

91

01

6

14

42

89

7

17

28

00

0

20

48

38

3

24

06

10

4

28

03

22

1

32

41

79

2

37

23

87

5

42

51

52

8

48

26

80

9

54

51

77

6

61

28

48

7

68

59

00

0

76

45

37

3

Tie

mp

o d

e p

roce

sam

ien

to (

ms)

Cantidad de numero procesados

Procesamiento de cuadraturas mediante CPU y GPU

GPU-Time [ms] CPU-Time [ms]

Page 22: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

21

De los datos obtenidos se calculó la desviación estándar de los tiempos de GPU, tiempos de CPU y

de la diferencia de tiempos, los datos son los siguientes:

Tiempos Desviación Estándar (ms)

GPU 0,209329566

CPU 12,07943149

Diferencia entre GPU y CPU 11,91521632

Se puede observar del gráfico que antes de los 25.000 elementos la CPU procesa mucho más

rápido, sin embargo la GPU procesa con tiempos casi constantes en todo su trayecto. Se obtuvo el

porcentaje de la diferencia de tiempos desde que se cruzan las líneas y se obtuvieron los

siguientes resultados:

Porcentaje de diferencia

Promedio 92,22 %

Máximo 98,40 %

Mínimo 16,48 %

Conclusiones del proyecto Como conclusiones del proyecto, se puede notar una notable ventaja por parte de la GPU en

cálculo de grandes arreglos de datos donde se puede encontrar una diferencia del 90%

aproximadamente, lo cual presenta una ventaja amplia respecto de solo el cómputo dentro de la

CPU. Si además le agregamos el poder de cómputo conjunto, se puede suponer un aumento del

rendimiento cercano a un 100%.

Conclusiones generales CUDA presenta un modelo de programación y de memoria bastante simple y de fácil uso, que

facilita lidiar con procesamientos múltiples de datos y hace uso del poder de cómputo de la GPU,

por lo que logra potenciar el rendimiento general a un nivel bastante amplio. CUDA además

presenta un modelo escalable independiente al modelo de programación por lo que resulta un

esfuerzo muy pequeño o nulo el escalar el código.

Page 23: CUDA Overview and Programming modeljsilva/cc68w-es.pdf · Un kernel de CUDA es ejecutado por un arreglo de threads, donde cada thread corre el mismo código y se diferencian por un

22

Referencias

Wikipedia:

http://es.wikipedia.org/wiki/CUDA, http://en.wikipedia.org/wiki/CUDA

NVIDIA developer zone:

http://developer.nvidia.com/object/cuda_training.html

NVIDIA Cuda Home:

http://www.nvidia.com/object/cuda_home_new.html

Dr. Dobb’s – CUDA, Supercomputing for the masses:

http://www.drdobbs.com/high-performance-computing/207200659

NVIDIA TESLA product information:

http://www.nvidia.com/object/tesla_computing_solutions.html

NVIDIA CUDA Download

http://developer.nvidia.com/object/cuda_3_2_downloads.html

San Diego Supercomputer Center – Training

http://www.sdsc.edu/us/training/workshops.php?status=past

NVIDIA CUDA Library Documentation

http://developer.download.nvidia.com/compute/cuda/3_2/toolkit/docs/online/index.html


Recommended