Así es como funciona el dispatch de hilos en GPU

El dispatch de hilos en GPU es el proceso de asignación y lanzamiento de grupos de hilos hacia las unidades de ejecución. Se basa en la organización de hilos en warps (o wavefronts), que son gestionados por un programador de hardware para maximizar la ocupación del chip.
La arquitectura de una GPU no procesa hilos de forma aislada como un CPU. En su lugar, utiliza un modelo de ejecución masivamente paralelo donde el hardware decide qué grupo de hilos debe acceder a las unidades aritméticas en cada ciclo de reloj.
{inAds}
La jerarquía de ejecución y el flujo de despacho
El proceso comienza cuando el host (CPU) envía un kernel a la GPU. El GigaThread Engine (en arquitecturas NVIDIA) actúa como el despachador global. Este componente distribuye los bloques de hilos entre los distintos multiprocesadores de flujo (Streaming Multiprocessors o SM).
Una vez que un bloque llega al SM, el dispatch se vuelve más granular. El SM no ejecuta el bloque completo a la vez, sino que lo divide en unidades menores llamadas warps, generalmente compuestas por 32 hilos.
El rol del Warp Scheduler
El Warp Scheduler es el cerebro del dispatch interno. Su función es elegir, en cada ciclo, cuál warp está listo para ejecutar una instrucción. No todos los warps pueden avanzar simultáneamente debido a que pueden estar esperando datos de la memoria global o el resultado de una operación matemática compleja.
Cuando un warp se bloquea por una latencia de memoria, el scheduler realiza un cambio de contexto instantáneo. Selecciona otro warp que tenga sus operandos listos y lo despacha a las unidades de ejecución. Este mecanismo es lo que permite que la GPU oculte la latencia de acceso a los datos.
Mecanismos de ejecución SIMT
El dispatch de hilos en GPU se rige por el modelo SIMT (Single Instruction, Multiple Threads). A diferencia del SIMD tradicional, donde una sola instrucción opera sobre un vector, el SIMT permite que cada hilo tenga su propio contador de programa (Program Counter).
Sin embargo, el hardware despacha la instrucción a todo el warp simultáneamente. Esto significa que los 32 hilos ejecutan la misma operación sobre diferentes datos.
Divergencia de hilos y máscaras de ejecución
Cuando el código contiene una sentencia condicional (como un if/else), ocurre la divergencia. Si algunos hilos del warp deben seguir el camino A y otros el camino B, el dispatch no puede ejecutar ambos a la vez.
El hardware resuelve esto mediante el uso de máscaras de ejecución. El scheduler despacha primero la ruta A mientras desactiva los hilos que deben ir por la ruta B. Luego, invierte el proceso. Esto reduce la eficiencia del dispatch, ya que parte de la capacidad de cómputo queda inactiva durante estas fases.
Especificaciones del flujo de datos en el dispatch
El rendimiento del dispatch depende de la capacidad del SM para gestionar múltiples warps activos. A continuación se detallan los componentes críticos involucrados:
| Componente | Función en el Dispatch | Impacto en el Rendimiento |
|---|---|---|
| Register File | Almacena el estado de todos los hilos activos | Limita la cantidad de warps residentes |
| Warp Scheduler | Selecciona el warp listo para ejecutar | Determina la tasa de instrucciones por ciclo |
| Dispatch Unit | Envía la instrucción a las ALU | Define el ancho de banda de ejecución |
| Shared Memory | Intercambio rápido de datos entre hilos | Reduce la dependencia de la memoria global |
Dispatch de GPU frente a Multithreading de CPU
El modelo de dispatch de una GPU difiere radicalmente del Context Switching de un procesador central. Mientras que el CPU busca minimizar la latencia de un solo hilo, la GPU busca maximizar el rendimiento total (throughput).
En un CPU, el cambio de contexto es costoso. Requiere guardar el estado de los registros en la memoria y cargar el de otro hilo, lo que consume miles de ciclos. En cambio, la GPU mantiene el estado de cientos de hilos directamente en el Register File. El dispatch es casi instantáneo porque no hay que mover datos entre niveles de memoria para cambiar de hilo.
El CPU utiliza predicción de saltos y ejecución fuera de orden para evitar esperas. La GPU ignora estas técnicas y simplemente despacha un grupo de hilos diferente mientras el anterior espera sus datos.
Optimización del despacho de instrucciones
Para que el dispatch sea eficiente, es necesario mantener una alta ocupación. La ocupación es la relación entre el número de warps activos en un SM y el número máximo de warps que el hardware puede soportar.
Si un kernel utiliza demasiados registros por hilo, el SM puede alojar menos warps. Esto reduce la capacidad del scheduler para ocultar la latencia. Cuando hay pocos warps disponibles y todos están esperando datos de la VRAM, las unidades de cómputo quedan vacías, provocando que el dispatch se detenga momentáneamente.
El uso de memoria compartida ayuda a optimizar este proceso. Al reducir las peticiones a la memoria global, los warps pasan menos tiempo en estado de espera y el scheduler puede mantener un flujo de instrucciones constante hacia las unidades de ejecución.
Dudas comunes sobre la ejecución de hilos
¿Cuántos hilos puede ejecutar una GPU simultáneamente?
La cifra depende del número de Streaming Multiprocessors y la cantidad de registros disponibles por SM. En arquitecturas modernas, una GPU puede tener miles de hilos residentes, pero solo una fracción pequeña se ejecuta en el mismo ciclo de reloj a través de las unidades aritméticas.
¿Qué pasa si uso el 100% de mi GPU?
Cuando el uso llega al límite, el dispatch sigue funcionando pero la GPU alcanza su saturación de cómputo o de ancho de banda de memoria. El scheduler sigue alternando warps, pero ya no hay margen para absorber más carga, lo que puede resultar en un aumento de la temperatura y el mantenimiento de la frecuencia de reloj máxima permitida por el Power Limit.
¿Cómo funciona la GPU compartida?
En entornos de virtualización o GPU compartida, el dispatch se gestiona mediante un hipervisor o capas de software que dividen los recursos del hardware. Dependiendo de la tecnología, se puede realizar un reparto temporal (Time-Slicing), donde cada instancia recibe turnos de despacho, o un reparto espacial, donde se asignan SMs específicos a cada usuario.