domingo, 8 de noviembre de 2009

Multithreading en GPUs

El multithreading en los procesadores de proposito general es una técnica muy común. Para aprovechar al máximo los recursos disponibles, en colaboración con el sistema operativo, se pueden procesar intrucciones de 2 o más hilos simultaneamente, aprovechando así el paralelismo a nivel de hilo.

En las tareas para las que se diseñan los procesadores gráficos, el paralelismo es fácilmente aprovechable. Hay cálculos que deben realizarse para cada vértice o para cada fragmento, lo que significa repetir la misma tarea una y otra vez sobre diferentes datos en memoria, por lo que el paralelismo y la idea de multithreading es básica en el diseño de GPUs actuales. Veamos un esquema de la arquitectura de un procesador gráfico moderno.


Como se puede ver, la arquitectura del ejemplo hay unas pocas estructuras hardware que están replicadas varias veces. Esto es una señal de que el diseño está hecho para aprovechar el paralelismo. Cada uno de los cuadrados verdes está representando un pequeño procesador, capaz de realizar operaciones encoma flotante. Las estructuras de control crean un hilo para cada operación que ha de realizase, ya esta esta relacionada con vertices, geometría o fragmentos. Estos hilos se asignan a una de las unidades de ejecución, que realiza la tarea y termina. Estos hilos, aunque comparten nombre con los que usamos en los sistemas operativos y CPUs actuales. La idea es la misma, es decir ejecutar en paralelo distintas partes de código compartiendo la memoria. Sin embargo, no tienen mecanismos como semaforos, o mutexes. Son mucho más simples y no requieren una gestión complicada.

La idea de hilos en una GPU se puede representar con el siguiente ejemplo. Imaginemos que queremos sumar las matrices A y B, de tamaño 1000x1000. Si pensamos en un solo hilo, el algoritmo sería algo parecido a lo siguiente:

for (i = 0; i<1000; i++)
    for (j=0; j<1000; j++)
         C[i,j]=A[i,j]+B[i,j]

Si quisieramos ejecutar esto en una GPU, la estrategia consiste en crear 1000x1000 hilos, cada uno de los cuales hace una suma y entre todos completan la matriz C con el resultado. Estos hilos se distribuyen por las numerosas unidades de ejecución, por lo que el nivel de paralelismo es altísimo. Como ya se ha dicho antes, no hay mecanismos complejos para sincronizar los hilos o reservar recursos. Esto sin embargo no es un problema, ya que como se puede ver, los hilos que se generan son muy simples y no necesitan este tipo de facilidades.

La capacidad de las GPUs actuales de realizar ciertos calculos de una manera muy eficiente, aprovechando el paralelismo como hemos visto, ha hecho que además de para generar gráficos, se utilicen en otras disciplinas como en cálculo científico, donde ciertos problemas pueden descomponerse en multitud de hilos que realizan pequeñas operaciones, ejecutándose en la GPU con un rendimiento mucho mayor que en la CPU.

Patxi Astiz

No hay comentarios:

Publicar un comentario