CAPACIDAD COMPUTACIONAL -...

14
PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL TECNOLOGÍA CUDA 45 IV. CAPACIDAD COMPUTACIONAL: Debido al uso de la tecnología CUDA en computación numérica, se han definido una serie de capacidades que ofrecen más información acerca del rendimiento de los dispositivos CUDA en este campo. NVIDIA define 5 clases de capacidad computacional En la Tabla 1 se muestran algunas de las tarjetas comercializadas por NVIDIA indicando la versión de Capacidad Computacional que le corresponde y cuyo interés es relevante para el presente proyecto; bien por su importancia en la literatura y las fuentes consultadas como la 8800 y 5600, bien por su uso en alguna de las fases del proyecto como 9500 y la 260 o bien para permitir una mejor comparación con equipos más sofisticados especialmente diseñados para las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos Multiprocesadores Capacidad computacional 9500 GT 32 4 1.1 8800 ultra 128 16 1.0 260 GTX 192 24 1.3 FX5600 128 16 1.0 Tesla C870 128 16 1.0 Tesla C1060 240 30 1.3 Tesla C2050 448 14 2.0 Tabla 1: Resumen de algunas características de GPUs CUDA.

Transcript of CAPACIDAD COMPUTACIONAL -...

Page 1: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

45

IV. CAPACIDAD COMPUTACIONAL:

Debido al uso de la tecnología CUDA en computación numérica, se han

definido una serie de capacidades que ofrecen más información acerca

del rendimiento de los dispositivos CUDA en este campo.

NVIDIA define 5 clases de capacidad computacional

En la Tabla 1 se muestran algunas de las tarjetas comercializadas por

NVIDIA indicando la versión de Capacidad Computacional que le

corresponde y cuyo interés es relevante para el presente proyecto;

bien por su importancia en la literatura y las fuentes consultadas

como la 8800 y 5600, bien por su uso en alguna de las fases del

proyecto como 9500 y la 260 o bien para permitir una mejor

comparación con equipos más sofisticados especialmente diseñados para

las tareas computacionales de alto nivel como la familia Tesla.

Tarjeta Núcleos Multiprocesadores Capacidad

computacional

9500 GT 32 4 1.1

8800 ultra 128 16 1.0

260 GTX 192 24 1.3

FX5600 128 16 1.0

Tesla C870 128 16 1.0

Tesla C1060 240 30 1.3

Tesla C2050 448 14 2.0

Tabla 1: Resumen de algunas características de GPUs CUDA.

Page 2: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

46

En la Tabla 2 se indican las capacidades y especificaciones técnicas

del equipo disponibles según la versión soportada.

CAPACIDAD COMPUTACIONAL 1.0 1.1 1.2 1.3 2.0

Funciones atómicas de

enteros con operandos de

32 bits en memoria Global

NO Sí

Funciones atómicas de

enteros con operandos de

64 bits en memoria Global

NO Sí

Funciones atómicas de

enteros con operandos de

32 bits en memoria

Compartida

Funciones de voto Warp

Números con precisión

double.

NO Sí

Suma atómica de tipo float

con operandos de 32 bits

almacenados en memoria

compartida o en memoria

global. NO Sí

__ballot()

__threadfence_system()

__syncthreads_count(),

__syncthreads_and(),

__syncthreads_or() ;

Tamaño máximo de las

dimensiones “x” o “y” en

la definición de la Malla.

65535

Máximo número de hilos por

bloque.

512 1024

Tamaño máximo de las

dimensiones “x” o “y” en

la definición de un

Bloque.

512 1024

Tamaño máximo de la

dimensión “z” de un

bloque.

64

Tamaño del Warp.

32

Número máximo de bloques

residentes en un

multiprocesador.

8

Número máximo de Warps

residentes en un

multiprocesador.

24 32 48

Número máximo de hilos

residentes en un

multiprocesador.

768 1024 1536

Número de registros de 32

bits por Multiprocesador. 8K 16K 32K

Tamaño máximo de la

memoria compartida para

cada Multiprocesador.

16K 48K

Número de bancos de

memoria compartida. 16 32

Tamaño de memoria local

por hilo. 16KB 512KB

Tamaño de la memoria

constante. 64KB

Caché asignada a la

memoria constante por

multiprocesador.

8KB

Page 3: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

47

Caché asignada a la

memoria de Textura por

multiprocesador.

Entre 6KB y 8KB dependiendo del

dispositivo.

Anchura máxima para una

referencia 1D de textura

vinculada a un array CUDA.

8192 8192

Anchura máxima para una

referencia 1D de textura

vinculada a memoria

lineal.

2

Anchura y altura máximas

para una referencia 2D de

textura vinculada a

memoria lineal o a un

array CUDA.

65536 x 32768 65536 x

65536

Anchura altura y

profundidad máximas para

una referencia 3D de

textura vinculada a

memoria lineal o a un

array CUDA.

2048 x 2048 x 2048

4096 x

4096 x

4096

Número máximo de

instrucciones por kernel 2 millones

Tabla 2: Características del dispositivo según la Capacidad

Computacional.

1. ESTÁNDAR DE COMA FLOTANTE:

El estándar de la IEEE para aritmética en coma flotante (IEEE 754) es

el estándar más extendido y es usado por la mayoría de las CPUs y

GPUs. El estándar define formatos para la representación de números

en coma flotante (incluyendo el cero) y valores desnormalizados, así

como valores especiales como infinito y NaN, con un conjunto de

operaciones que usan este tipo de datos. También especifica cuatro

modos de redondeo y cinco excepciones (incluyendo cuándo ocurren

dichas excepciones y qué sucede en esos momentos).

IEEE 754 especifica cuatro formatos para la representación de valores

en coma flotante: precisión simple (32 bits), precisión doble (64

bits), precisión simple extendida (≥ 43 bits, no usada normalmente) y

precisión doble extendida (≥ 79 bits, usualmente implementada con 80

bits). Sólo los valores de 32 bits son requeridos por el estándar,

los otros son opcionales. Muchos lenguajes especifican qué formatos y

aritmética de la IEEE implementan, a pesar de que a veces son

opcionales. Por ejemplo, el lenguaje de programación C, ahora permite

pero no requiere la aritmética de la IEEE (el tipo de C float es

típicamente usado para la precisión simple de la IEEE y el tipo

double usa la precisión doble de la IEEE).

El título completo del estándar es “754-2008 IEEE Standard for

Floating-Point Arithmetic” que es la actualización del estándar “IEEE

Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std 754-

1985)”.

Page 4: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

48

Todos los dispositivos CUDA soportan el estándar IEEE 754-2008 con

las siguientes particularidades:

No existe un modo de redondeo configurable dinámicamente, la

mayoría de las operaciones soportan múltiples modos de

redondeo.

No hay un mecanismo para detectar si se ha producido una

excepción de tipo coma flotante. Todas las operaciones se

comportan como si las excepciones quedaran enmascaradas.

El resultado de una operación con precisión simple con

operandos tipo NaNs es el Nan discreto con el patrón de bits

0x7fffffff.

Las operaciones de valor absoluto y negativo en precisión doble

no cumplen el estándar. Los NaNs son pasados sin cambios.

2. PRECISIÓN SIMPLE EN DISPOSITIVOS DE CAPACIDAD COMPUTACIONAL 1.X:

La precisión simple o float se soporta según el estándar, pero con

las siguientes excepciones:

Los números desnormalizados no son soportados. La aritmético en

coma flotante y las instrucciones de comparación convierten

estos operandos en cero.

Subdesbordamiento: los valores son igualados a cero.

Algunas instrucciones no cumplen el estándar de la IEEE.

Las operaciones suma seguida de multiplicación son

generalmente combinadas en una operación única de

multiplicación-adición (FMAD), que trunca sin redondear la

mantisa del producto.

La división se implementa mediante la operación reciproca de

forma no estándar.

-La raíz cuadrada se implementa mediante la recíproca también

de forma no estándar.

Para las operaciones de producto y suma exclusivamente, el

redondeo al par más cercano y el redondeo a cero se implementan

mediante modos estáticos. El redondeo a + y – infinito no es

soportado.

Page 5: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

49

Para contrarrestar el efecto de estas restricciones, se proporcionan

implementaciones estándar aunque más lentas mediante las funciones

intrínsecas siguientes:

__fmaf_r{n,z,u,d}(float, float, float): Operación producto-

Adición fusionadas según el estándar de redondeo de IEEE.

__frcp_r[n,z,u,d](float): Operación de recíproco según el

estándar de redondeo de IEEE.

__fdiv_r[n,z,u,d](float, float): Operación de división según el

estándar de redondeo de IEEE.

__fsqrt_r[n,z,u,d](float): Operación de raíz cuadrada según el

estándar de redondeo de IEEE.

__fadd_r[u,d](float, float): Operación de Suma según el

estándar de redondeo de IEEE.

__fmul_r[u,d](float, float): Operación de Producto según el

estándar de redondeo de IEEE.

3. PRECISIÓN DOBLE EN DISPOSITIVOS DE CAPACIDAD COMPUTACIONAL 1.X:

En precisión doble o double sólo es soportado el modo de redondeo al

par más cercano para el reciproco, división, y raíz cuadrada según el

estándar IEEE.

Cuando se compila código para un dispositivo que no soporta double

(es decir, en dispositivos con capacidad computacional 1.2 o

anterior) cada variable double es convertida en una float(aunque el

dato sigue estando almacenado en 64 bits) y las operaciones

aritméticas se realizan en precisión simple. Para dispositivos tipo

2.0 y superior, el código debe ser compilado con las instrucciones -

ftz=false, -prec-div=true, y -prec-sqrt=true para garantizar que el

código es acorde al estándar IEEE. Para dispositivos tipo 1.x se debe

compilar con las ordenes: -ftz=true, -prec-div=false, y -prec-

sqrt=false.

La suma seguida de multiplicación son fusionadas habitualmente en una

única operación multiplicación-suma llamada FMAD con dos versiones

para ser compatible con cada uno de los dos tipos de capacidad

computacional.

FMAD para precisión simple en dispositivos de capacidad 1.x.

FFMA para precisión simple en dispositivos de capacidad 2.0.

La operación FMAD trunca la mantisa antes de usar el dato en la fase

de suma. En cambio la FFMA cumple con el estándar IEEE-754(2008) y se

usa la extensión complete del dato de la multiplicación en la

instrucción de suma y se produce un único redondeo al final de la

operación completa.

Page 6: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

50

4. DISPOSITIVOS DE CAPACIDAD COMPUTACIONAL TIPO 1.X:

a. ARQUITECTURA:

En dispositivos de capacidad computacional 1.x un multiprocesador

está formado por:

8 núcleos dedicados a operaciones aritméticas de enteros y coma

flotante de precisión sencilla.

1 unidad para aritmética de coma flotante con precisión doble.

2 unidades funcionales especiales para operaciones

trascendentales con operandos de precisión sencilla. (Estas

unidades pueden también realizar productos en coma flotante

sencilla).

-1 organizador de Warps: Para ejecutar una instrucción para un

Warp el organizador debe ejecutar las órdenes según el siguiente

esquema:

- 4 ciclos de reloj para operaciones aritméticas de enteros y

floats.

- 32 ciclos de reloj para operaciones con precisión doble.

- 16 ciclos de reloj para operaciones trascendentales con

precisión float.

Un Multiprocesador dispone de una Caché constante de lectura que es

compartida entre las unidades funcionales que acelera y lee de la

memoria constante del dispositivo.

Los Multiprocesadores son agrupados en Clusers de Procesado de

Textura (Texture Processor Clusters (TPCs)).

2 Multiprocesadores por TPC en dispositivos de tipo 1.0 y 1.1.

3 Multiprocesadores por TPC en dispositivos de tipo 1.2 y 1.3.

Cada TPC tiene una Caché de lectura en modo sólo lectura que es

compartida por todos los multiprocesadores y que acelera y lee del

espacio de memoria de Textura del dispositivo. Cada Multiprocesador

accede a la cache de textura mediante una unidad de textura que

implementa los distintos modos de llamada y de filtrado.

b. MEMORIA GLOBAL

El acceso a la memoria Global por parte de un Warp se divide en dos

solicitudes, una para cada medio-Warp, que son emitidas de manera

independiente. Los accesos de memoria de los hilos de cada medio-Warp

son amalgamados en una o más solicitudes de transacciones de memoria

dependiendo de la capacidad computacional del dispositivo.

Page 7: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

51

En un dispositivo tipo 1.0 o 1.1 las solicitudes amalgamadas de cada

medio Warp se ejecutan del siguiente modo:

El tamaño de las palabras accedidas por un hilo deben ser de 4,

8 o 16 bytes.

Si el tamaño es 4, las 16 palabras deben estar dispuestas en el

mismo segmento de 64 bytes.

Si el tamaño es 8, las 16 palabras deben estar dispuestas en el

mismo segmento de 128 bytes.

Si el tamaño es 16, las primeras 8 palabras deben estar

dispuestas en el mismo segmento de 128 bytes, y las 8 palabras

siguientes dispuestas en el bloque siguiente de 128 bytes.

Los accesos deben ser secuenciales, de tal modo que el enésimo-

hilo del medio-warp debe acceder a la enésima palabra.

Si el medio-warp cumple estos requisitos se emiten sendas órdenes de

transacción de memoria de 64 bytes, 128 bytes y de dos de 128 bytes.

La amalgama se realiza incluso en caso de divergencia en la

ejecución. En el caso de que no se cumplan estas condiciones se

emiten 16 órdenes de 32 bytes.

En un dispositivo tipo 1.2 o 1.3 los hilos pueden acceder a los datos

en cualquier orden, incluso acceder a los mismos datos. En esos

casos, una instrucción única de acceso de memoria es emitida por el

medio-Warp. A diferencia de lo que pasa en los dispositivos 1.0 y

1.1; donde el acceso debe ser secuencial y la amalgama sólo se

produce si el medio-Warp accede a un único segmento de memoria.

Page 8: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

52

El protocolo siguiente es el seguido para establecer las

transacciones necesarias para ejecutar las solicitudes emitidas por

los hilos de un Medio-Warp:

-Localizar el segmento de memoria que contiene las direcciones

solicitadas por el hilo activo de número más bajo.

El tamaño del segmento dependerá del tamaño de las palabras

solicitadas:

o -32 bytes para palabras de 1 byte.

o -64 bytes para palabras de 2 byte.

o -128 bytes para palabras de 4, 8 y 16 bytes.

-Localizar los demás hilos activos con solicitudes dirigidas al

mismo segmento.

-Reducir si es posible el tamaño de la transacción.

-Si el tamaño de la transacción es de 128 bytes y sólo se usa

una de las mitades se reduce el tamaño a 64 bytes.

-Si el tamaño de la transacción es de 64 bytes y sólo se usa

una de las mitades se reduce el tamaño a 32 bytes.

-Ejecutar las solicitudes y desactivar los hilos.

-Repetir hasta desactivar todos los hilos.

c. MEMORIA COMPARTIDA:

La memoria Compartida tiene 16 bancos organizados sucesivamente. Cada

banco tiene un ancho de banda de 32 bits por cada dos ciclos de

reloj.

La solicitud de memoria compartida realizada por un Warp se separa en

dos solicitudes de memoria. Una para cada medio-Warp que son

emitidas de manera independiente. Como consecuencia no debería haber

conflictos entre los hilos pertenecientes a cada medio-Warp.

Si una instrucción no-atómica, que es ejecutada por un Warp, pretende

que más de un hilo del warp escriban en la misma posición de la

memoria compartida, entonces sólo un hilo de cada medio-Warp

realizará la operación de escritura. De hecho queda indefinido cuál

de los hilos realiza la última escritura.

Accesos en zancadas de 32 bits (strided):

Un modo de acceso habitual para los hilos es a palabras de 32 bits

desde un array indexado por la identidad del hilo tid y con un tamaño

determinado de zancada “s”, por ejemplo mediante el código siguiente:

__shared__ float shared[32];

float data = shared[BaseIndex + s * tid];

Page 9: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

53

En este caso los hilos tid and tid+n acceden al mismo banco siempre y

cuando s*n sea un múltiplo del número de bancos (p.e. 16) o de manera

similar cuando n es un múltiplo de 16/d donde d el máximo común

divisor de 16 y “s”. En ese caso se evitará que haya conflicto de

acceso a bancos siempre que el tamaño del medio-warp (16) sea igual o

inferior a 16/d lo cual se cumple cuando d es 1 y por tanto s es

impar.

Accesos en modo Difusión (Broadcast):

Las memorias compartidas disponen de un mecanismo de difusión donde

las palabras de 32 bits pueden ser accedidas y difundidas a varios

hilos simultáneamente, ejecutando una sola instrucción de acceso de

memoria. Este método reduce enormemente los conflictos de banco

cuando varios hilos leen direcciones del mismo dato de 32 bits. De

hecho para el caso de accesos de memoria realizados a varias

posiciones, lo que se hace es dividir el proceso en varios pasos;

ejecutando tantos accesos como sean necesarios para evitar conflictos

hasta completar todas las solicitudes. En cada paso se maneja un

grupo de direcciones según el protocolo siguiente:

Asignar una de las palabras apuntadas por las demás direcciones

como dirección de difusión.

Incluir en el grupo de direcciones:

- Todas las direcciones que están dentro de la palabra de

difusión.

- Una dirección para cada banco (excepto la del banco de

difusión) apuntadas por las demás direcciones.

Un ejemplo donde se evitan conflictos es cuando todos los hilos de un

medio-warp leen posiciones de memoria contenidas en la misma palabra

de 32 bits.

Accesos de 8 y 16 bits:

Los accesos de tipo 8-bit y 16-bit producen generalmente conflictos

de banco, por ejemplo cuando un array de tipo char es accedido

mediante:

__shared__ char shared[32];

char data = shared[BaseIndex + tid];

Esto es debido a que shared[0], shared[1], shared[2], y shared[3],

por ejemplo, pertenecen al mismo banco. Sin embargo se evitarían

conflictos si se accediesen mediante:

char data = shared[BaseIndex + 4 * tid];

Accesos de más de 32 bits:

Los accesos mayores de 32 bits por hilo son divididos en accesos de

32. Usualmente provocan conflictos de banco.

Page 10: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

54

En el ejemplo siguiente aparecen conflictos bi-direccionales para

arrays de tipo double cuando se acceden mediante:

__shared__ double shared[32];

double data = shared[BaseIndex + tid];

Ya que la solicitud de memoria se compila en dos solicitudes de 32

bits cada una con una zancada de 2. Para evitar estos conflictos se

divide los operandos double como se muestra en el siguiente ejemplo:

__shared__ int shared_lo[32];

__shared__ int shared_hi[32];

double dataIn;

shared_lo[BaseIndex + tid] = __double2loint(dataIn);

shared_hi[BaseIndex + tid] = __double2hiint(dataIn);

double dataOut =

__hiloint2double(shared_hi[BaseIndex + tid],

shared_lo[BaseIndex + tid]);

Este método puede no mejorar las prestaciones e incluso empeorarlas

en dispositivos tipo 2.0.

Lo mismo es aplicable a asignación de estructuras:

__shared__ struct type shared[32];

struct type data = shared[BaseIndex + tid];

Que se traduce en:

3 lecturas independientes sin conflicto si type se

define como: struct type {float x, y, z;}; ya que cada elemento

es accedido con una zancada impar de tres palabras de 32 bits.

-2 lecturas independientes con conflicto si type

se define como: struct type {float x, y;}; ya que cada elemento

es accedido mediante una zancada par de dos palabras de 32bits.

Page 11: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

55

5. DISPOSITVOS DE CAPACIDAD COMPUTACIONAL 2.0:

a. ARQUITECTURA:

Para dispositivos de tipo 2.0 un Multiprocesador está compuesto por:

-32 núcleos CUDA para operaciones aritméticos con enteros y con

operandos en coma flotante.

-4 unidades funcionales especiales para funciones

trascendentales con operandos de coma flotante.

2 organizadores de Warps.: Cada organizador genera una

instrucción para que sea ejecutada por un Warp active. El

primer organizador gestiona los Warps con índice impar y el

segundo se encarga de los de índice par. Sin embargo cuando un

organizador manda una orden en precisión double el otro

organizador permanece inactivo.

Un organizador manda instrucciones a la mitad de los núcleos.

Por tanto para ejecutar una orden para todos los hilos de un

warp, el organizador debe emplear:

- 2 ciclos de reloj para una instrucción aritmética de

tipo entero o float.

- 2 ciclos de reloj para una instrucción aritmética de

tipo double.

- 8 ciclos de reloj para una instrucción trascendental de

tipo float.

Un Multiprocesador posee una única Caché en modo solo lectura que se

comparte por todas las unidades funcionales y acelera los accesos de

la memoria constante del dispositivo.

Existe una memoria caché L1 para cada Multiprocesador y una Caché L2

compartida por todos los Multiprocesadores, ambas son usadas para

almacenar los accesos a las memorias local y global del dispositivo.

El comportamiento de la Caché y su gestión pueden ser parcialmente

configuradas usando modificadores de las instrucciones de carga y

almacenamiento.

La misma memoria de chip se usa tanto para la memoria compartida como

para L1: Se puede configurar como 48KB de memoria compartida con 16

KB de Caché L1 o como 16KB de memoria compartida y 48 KB de L1 usando

la instrucción cudaFuncSetCacheConfig() o cuFuncSetCacheConfig(),

como ilustra el siguiente ejemplo de código:

// Device code

__global__ void MyKernel()

{

...

}

Page 12: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

56

// Host code

// Runtime API

// cudaFuncCachePreferShared: shared memory is 48 KB

// cudaFuncCachePreferL1: shared memory is 16 KB

// cudaFuncCachePreferNone: no preference

cudaFuncSetCacheConfig(MyKernel, cudaFuncCachePreferShared)

// Driver API Appendix G. Compute Capabilities 156 CUDA C

Programming Guide Version 3.1

// CU_FUNC_CACHE_PREFER_SHARED: shared memory is 48 KB

// CU_FUNC_CACHE_PREFER_L1: shared memory is 16 KB

// CU_FUNC_CACHE_PREFER_NONE: no preference

CUfunction myKernel;

cuFuncSetCacheConfig(myKernel, CU_FUNC_CACHE_PREFER_SHARED)

Los Multiprocesadores se agrupan en Razimos de Procesamiento Gráfico

(Graphics Processor Clusters (GPCs)). Cada GPC está compuesto por 4

Multiprocesadores.

Cada Multiprocesador posee una Caché Textura en modo sólo lectura de

la memoria de Textura del dispositivo. Se accede a dicha Caché

mediante una unidad particular que implementa los modos de

direccionamiento y filtros de datos.

b. MEMORIA GLOBAL:

Los accesos a la memoria Global son almacenados en la Caché usando la

bandera de compilación–dlcm que permite configurar el destino de

almacenamiento L1 o L2.

Para almacenar en L1 y L2 se usa la instrucción por defecto:(-Xptxas

-dlcm=ca) y para almacenar en L2 se usa la instrucción (-Xptxas -

dlcm=cg).

Una línea de memoria tanto en L1 como en L2 es de 128 bytes y es

mapeada a un segmento del mismo tamaño en la memoria del dispositivo.

Si el tamaño de los datos accedidos por cada hilo es superior a 2

bytes, entonces los accesos del warp se dividen en solicitudes de 128

bytes independientes entre sí de tal modo que:

2 solicitudes de memoria; una para cada medio-warp si el tamaño

es de 8 bytes.

4 solicitudes de memoria; una para cada medio-warp si el tamaño

es de 16 bytes.

Page 13: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

57

Cada solicitud de memoria se divide en solicitudes de Caché que se

ejecutan independientemente.

Los hilos pueden acceder a cualquier dato en cualquier orden, incluso

acceder a los mismos datos.

Si una instrucción no-atómica ejecutada por un warp escribe en la

misma posición de la memoria global, sólo un hilo realizará dicha

escritura.

c. MEMORIA COMPARTIDA:

La memoria compartida se organiza en 32 bancos de tal modo que

palabras consecutivas de 32 bits son asignadas a bancos consecutivos.

Cada banco posee un ancho de banda de 32 bits por cada dos ciclos de

reloj. Por tanto a diferencia de los dispositivos tipo 1.x, puede

haber conflicto entre hilos perteneciente a distintas mitades del

mismo warp.

Un conflicto se produce sólo si 2 o más hilos acceden a un byte

cualquiera perteneciente a palabras distintas de 32 bytes

pertenecientes al mismo banco. Si dos o más hilos acceden a cualquier

byte contenido en la misma palabra de 32 bits, no habrá conflicto. Ya

que para accesos de lectura, el dato es difundido a los hilos que lo

solicitan(A diferencia de lo que sucede en dispositivos tipo 1.x ;

varios datos pueden se difundidos mediante una única transacción).

Para procesos de escritura, cada byte es escrito por un único hilo.

Esto significa en concreto que a diferencia de los dispositivos tipo

1.x no hay conflicto de banco si un array de tipo char se accede de

la manera siguiente:

__shared__ char shared[32];

char data = shared[BaseIndex + tid];

Acceso de 32 bits en modo zancada (strided):

Es habitual que un hilo acceda a datos de 32 bits a partir de un

array indexado por índice del hilo tid y con una zancada “s”:

__shared__ float shared[32];

float data = shared[BaseIndex + s * tid];

En este caso los hilos tid y tid+n acceden al mismo banco siempre y

cuando s*n sea un múltiplo del número de bancos (es decir de 32), o

lo que es lo mismo, siempre que n sea múltiplo de 32/d donde “d” es

el mayor divisor común de 32 y “s”. Por tanto no habrá conflicto

siempre y cuando el tamaño del warp (32) sea igual o inferior a 32/d,

es decir cuando “d” sea igual a uno y, por tanto, cuando “s” sea

impar.

Accesos superiores a 32 bits:

Los accesos de tipo 64-bit y 128-bit son gestionados de tal modo que

se minimizan los conflictos de banco como se describe más adelante.

Page 14: CAPACIDAD COMPUTACIONAL - bibing.us.esbibing.us.es/proyectos/abreproy/11926/fichero/Segunda+parte... · las tareas computacionales de alto nivel como la familia Tesla. Tarjeta Núcleos

PROGRAMACIÓN EN EL ENTORNO CUDA EN APLICACIONES DE MECÁNICA COMPUTACIONAL

TECNOLOGÍA CUDA

58

Los demás accesos superiores a 32 bits son divididos en accesos de

32, 64 o 128 bits.

El siguiente código produce 3 lecturas independientes de 32 bits sin

conflictos de banco ya que cada elemento es accedido con una zancada

de 3 palabras de 32 bits:

struct type {

float x, y, z;

};

__shared__ struct type shared[32];

struct type data = shared[BaseIndex + tid];

Accesos de 64-bits.

Para los accesos de 64 bits se puede producir un conflicto de banco

únicamente si 2 o más hilos de cada medio-warp acceden a direcciones

diferentes pertenecientes al mismo banco.

A diferencia de los dispositivos tipo 1.x, no se producen conflictos

para arrays de tipo double en el ejemplo de código siguiente:

__shared__ double shared[32];

double data = shared[BaseIndex + tid];

Accesos de 128-bits.

La mayoría de los accesos de 128 bits producirán conflictos

bidireccionales, incluso si no hay hilos pertenecientes a un cuarto-

de-warp que accedan a diferentes direcciones pertenecientes al mismo

banco. Por tanto para determinar las rutas de los conflictos de

banco, se debe incrementar en uno el máximo número de hilos de un

cuarto-de-warp que acceden a distintas direcciones del mismo banco.

d. MEMORIA CONSTANTE:

Además de la memoria constante del dispositivo, los dispositivos de

capacidad 2.0 soportan La Instrucción de Carga Uniforme (LDU (LoaD

Uniform)), que permite al compilador almacenar cualquier variable

que:

Apunte a la memoria global.

Sea de sólo lectura en el Kernel.

Sea independiente de la identidad del hilo.