Buscar este blog

Mostrando entradas con la etiqueta tipos de memoria. Mostrar todas las entradas
Mostrando entradas con la etiqueta tipos de memoria. Mostrar todas las entradas

viernes, 2 de marzo de 2012

En busca del Kernel perdido


Con todo lo expuesto en los post anteriores debemos confeccionar nuestra lista de prioridades a la hora de diseñar los kernel que ejecuten las GPU. Resumiendo, debemos tener en cuenta los siguientes factores:

·         Factor de “unroll”

·         ILP: Nivel de Paralelización por instrucción

·         Factor de ocupación de la GPU, que se compone de:
o    Nº de bloques que se necesitan
o    Nº de hilos por cada bloque
o    Registros utilizados en el kernel

·         Transferencias de memoria CPU <-> GPU

·         Tipos de memoria a utilizar, Global, compartida,…


Teniendo todo esto en cuenta, nuestro kernel debe tener un número de instrucciones  mínimo que ocupe la latencia de la arquitectura, y se intentará invocar al kernel con el tamaño justo de bloques e hilos por bloques que maximicen la ocupación del tamaño  requerido. Se minimizará el número de transferencias de memoria entre CPU y GPU. Se intentará evitar las latencias de acceso a memoria global mediante accesos ordenados en memoria compartida.


En el próximo post, ilustraré con un ejemplo todo esto que hemos comentado


viernes, 24 de febrero de 2012

Los diversos usos de la memoria

Es muy importante saber que ventajas e inconvenientes tiene el uso de cada tipo de memoria de dispositivo, antes de realizar cualquier diseño, deberías tener claro cómo CUDA gestiona cada tipo de memoria, y cual es el coste o penalización que supone su utilización.


La siguiente Figura muestra los tipos de memoria en las GPUs y el ámbito de acceso de cada elemento
Figura 1. Los diferentes tipos de memoria en la GPU

Cada una de ellas tiene unos propósitos concretos que pasamos a detallar: Los registros y la memoria local son espacios de memoria accesibles únicamente por el hilo al que pertenecen. Por otro lado, a la memoria compartida  pueden acceder todos los hilos del mismo bloque, utilizando para ello mecanismos de sincronización que mantienen el orden en las lecturas y escrituras. Al resto de memorias  se puede acceder desde toda la malla que ejecuta un kernel. Se distinguen en que la memoria global no dispone de memoria caché, la memoria de constantes es de sólo lectura, y la memoria de texturas dispone de una caché espacial. 

El cuello de botella principal lo encontramos en la transferencia de memoria entre la CPU y la GPU, de modo que la penalización nos la encontramos en la latencia del acceso a la memoria global (entre 400 y 600 ciclos). Como solución posible se plantea el alineamiento de la memoria global para poder hacer lecturas ordenadas según la posición de cada hilo dentro de la tanda, se puede utilizar la memoria compartida para hacer la ordenación dentro de cada bloque. No siempre es posible hacer esta ordenación y el problema se complica cuando aumentan las dimensiones (matrices por ejemplo).