PUBLICO:Guia optimizacion GPU

De SOA - Wiki - Unlam
Revisión del 02:17 6 jul 2016 de Wvaliente (discusión | contribs.) (Página creada con « == Formatos que descarten datos ociosos == Los múltiples formatos de representación de matrices dispersas, tienen un doble beneficio. Estas poseen muy pocos elementos...»)
(difs.) ← Revisión anterior | Revisión actual (difs.) | Revisión siguiente → (difs.)
Ir a la navegación Ir a la búsqueda


Formatos que descarten datos ociosos

Los múltiples formatos de representación de matrices dispersas, tienen un doble beneficio. Estas poseen muy pocos elementos distintos de cero (menos al 10%). Los formatos buscan almacenar la información más valiosa minimizando el uso de recursos. Por un lado porque los valores en cero no interfieren en el resultado final del algoritmo, y por otro, se reduce considerablemente el uso de la memoria. En GPU tienen la ventaja que al reducir su consumo de memoria la información a transferir es menor y el acceso a memoria global (lenta), por el hilo kernel también disminuye. Como contra partida en lugar de hacer una sola transferencia (la matriz) se deben transferir los vectores que tienen la información valida. Agrupar transferencias. Bajo ciertas condiciones existe la posibilidad de beneficiarse en transferir entre CPU y GPU una sola vez, en lugar de dividir la transferencia en varias más pequeñas. Se transfiere la misma cantidad de información, lo que varía es la forma (Figura A).

Figura A - Comparación de transferencias simple o seriada. Esta situación se da cuando se preparan las pruebas sobre matrices dispersas enfocadas en los formatos de representación. El formato CRS está formado por tres vectores y hay otros como el formato de bloques BSR que se compone de cuatro vectores. Cada vector es transferido en eventos separados (Figura 28 A ). Mientras que existe el formato ELL con dos vectores, (Figura 28 B). Si se agrupan los vectores y se realiza una sola transferencia, se tiene la ventaja que se desprende de la secuencialidad de la CPU, que va invocando a las llamadas a biblioteca (API y Evento). Según sea la carga de la CPU esta puede generar tiempos de demora. Reutilización de variables globales en cache. Existen casos en el algoritmo sus datos están almacenados en memoria global y necesitan ser accedidas continuamente. Si estos son enviados a memoria interna del kernel, cuando el planificador no disponga de memoria, esta será enviada a la memoria local, que es de acceso lento. Para evitar esta situación se puede usar la memoria textura, que puede ser accedida por el CPU. La memoria de textura posee la particularidad de tener un nivel de memoria caché dentro del core GPU. Sí el dato almacenado en esta memoria solo es accedido por los hilos kernel una vez (Figura 29).

Figura 29 - Diagrama en bloques de memoria de textura Relación de lectura en memoria global comparada con la cantidad de hilos. Este parámetro requiere de un conocimiento de las variables que procesa el algoritmo en GPU (Figura 26 y 27). Se puede trazar una relación entre los accesos de lectura en memoria global, con la cantidad teóricamente calculada de lo que se espera que use el algoritmo con las propiedades de los datos de entrada. Si esta relación es negativa, significa que se accede menos a memoria global de lo estipulado (el algoritmo no estaría procesando todos los elementos). Si la relación es positiva, se está accediendo a memoria global más de lo esperado (Puede indicar que se está utilizando la memoria global para cuentas intermedias). En cero es el caso ideal. Relación de escritura en memoria global tendiente a cero. Un caso similar ocurre cuando el algoritmo escribe menos datos que los planificados. En este caso hay que comparar el valor teórico con el obtenido en los Contadores Hardware. Si es negativo el algoritmo se planifica mal, si es positivo está leyendo más cantidad de datos desde memoria global En caso de resultar negativo, puede mejorarse con auxiliares (memoria interna) para que solo se acceda una vez finalizado el algoritmo, desde el auxiliar.

Configuración ajuste minimalista de dimensiones. Por lo analizado en las pruebas de las bibliotecas BLAS. La mala elección del dimensionamiento está fijada por el algoritmo. La cantidad de hilos creados tiene relación con la configuración de dimensiones y a su vez, con la forma en que toma lógicamente esa topología de bloques/grillas en caso de NVIDIA o Grupo Local/Global en ATI. Una forma de evitar el caso anterior y este, de hilos que no impactan en todos los datos del algoritmo, es alinear al tamaño de warp para NVIDIA o wavefront en ATI. En la (Figura 30) se sobredimensiona la cantidad de hilos a ejecutar, dando hilos ociosos y desperdicio de recursos.


Fig. 30 - Ejemplo de hilos sobre-dimensionados.


Operación aritmética en su forma optima. La operación aritmética principal del algoritmo SPMV es la multiplicación de un elemento del vector con todos los elementos de la columna de la matriz. Cada multiplicación se acumula en una variable intermedia, interviniendo las operaciones de multiplicación, suma e igualación. Por simplicidad suele escribirse en seudocódigo como: Acumulador += Matriz[i][n] * vector[n] Se ha verificado que aumenta la cantidad de instrucciones por ciclo si se codifica de esta forma. Acumulador = Acumulador + ( Matriz[i][n] * vector[n] )

Esta mejora no es conmutativa y en cuanto a microinstrucciones del GPU la siguiente expresión da menos rendimiento. Acumulador = ( Matriz[i][n] * vector[n] ) + Acumulador

La diferencia surge debido a que la GPU está preparada para procesar en forma matemática con un orden definido de operaciones (igualdad – suma – multiplicación).