Resumen de la arquitectura de tiny-gpu
GPU
- Construida para ejecutar un kernel a la vez
- Para ejecutar un kernel, se requieren las siguientes tareas:
- Cargar la memoria global de programa con el código del kernel
- Cargar la memoria de datos con los datos necesarios
- Especificar en los registros de control del dispositivo la cantidad de hilos a ejecutar
- Poner la señal de inicio en HIGH para ejecutar el kernel
- La GPU está compuesta por las siguientes unidades:
- Registros de control del dispositivo
- Dispatcher
- Un número variable de núcleos de cómputo
- Controlador de memoria para la memoria de datos y la memoria de programa
- Caché
Memoria
- La GPU está construida para interactuar con memoria global externa
- La memoria de datos y la memoria de programa están separadas para simplificar el diseño
- La memoria global tiene un ancho de banda fijo de lectura/escritura
- El controlador de memoria rastrea todas las solicitudes salientes desde los núcleos de cómputo hacia la memoria, regula las solicitudes según el ancho de banda real de la memoria externa y retransmite las respuestas desde la memoria externa al recurso correspondiente
- La caché almacena datos solicitados repetidamente para reducir el uso del ancho de banda de memoria
Núcleos
- Cada núcleo cuenta con recursos de cómputo
- En esta GPU simplificada, cada núcleo procesa un bloque a la vez y tiene una ALU, LSU, PC y banco de registros dedicados para cada hilo del bloque
- El scheduler administra la ejecución de los hilos y no selecciona un nuevo bloque antes de completar el bloque actual
- El fetcher obtiene instrucciones de manera asíncrona desde el contador de programa actual
- El decoder decodifica las instrucciones obtenidas en señales de control para la ejecución de hilos
- Cada hilo tiene su propio conjunto dedicado de bancos de registros
- La ALU es una unidad aritmético-lógica dedicada por hilo
- La LSU es una unidad de carga/almacenamiento dedicada por hilo para acceder a la memoria global de datos
- El PC es un contador de programa dedicado que determina la siguiente instrucción a ejecutar en cada hilo
ISA
- Implementa una ISA simple de 11 instrucciones
- Construida para kernels simples como suma y multiplicación de matrices
- Soporta operaciones aritméticas básicas, carga/almacenamiento en memoria, saltos, carga de constantes y más
Ejecución
- Cada núcleo pasa por las etapas de fetch, decode, request, wait, execute y update para ejecutar instrucciones
- Cada hilo sigue una ruta de ejecución para realizar cálculos sobre los datos del banco de registros
- Para la funcionalidad SIMD, hay registros de solo lectura con valores de índice de bloque, dimensión e índice de hilo
Kernel
- Se escribieron kernels de suma y multiplicación de matrices en la ISA para demostrar la programación SIMD y la ejecución en GPU
- Con archivos de prueba se puede simular completamente la ejecución de kernels en la GPU y generar el estado de la memoria de datos y el rastro de ejecución
Simulación
- Después de instalar iverilog y cocotb, se puede ejecutar la simulación de kernels con el comando
make
- En el archivo de log se imprime el estado inicial/final de la memoria de datos y el rastro completo de ejecución del kernel
Funciones avanzadas
- Muchas funciones adicionales de las GPU modernas que mejoran enormemente el rendimiento y las capacidades se omiten para simplificar
- Se discuten funciones como cachés multinivel y memoria compartida, memory coalescing, pipelining, Warp scheduling, divergencia de ramas, sincronización y barreras
La opinión de GN⁺
- Explica muy bien, de forma simple y fácil de entender, los conceptos clave de la arquitectura de GPU y del modelo de programación SIMD. En particular, muestra claramente cómo se realiza el procesamiento paralelo en una GPU real mediante ejemplos de kernels de operaciones con matrices.
- También organiza bien las funciones avanzadas usadas en las GPU modernas, así que después de entender tiny-gpu puede servir de ayuda para estudiar arquitecturas de GPU más complejas.
- Sin embargo, no incluye funciones reales del pipeline gráfico, por lo que no aborda cómo funciona el hardware especializado en gráficos. Esto puede dejar con ganas de más a quienes estén interesados en gráficos.
- Compararlo con otras arquitecturas de GPU open source como MIAOW o GPGPU-Sim también puede ayudar a comprender GPU más realistas.
- Si en el futuro se agregan funciones como divergencia de ramas, memory coalescing o pipelining, podría convertirse en un material de aprendizaje aún más práctico. También resulta atractivo como proyecto open source al que se puede contribuir en el desarrollo.
1 comentarios
Comentarios de Hacker News
Intel publica mucha documentación técnica sobre GPU. Incluso se pueden encontrar en línea los manuales de 810/815. Salvo 855/910/915/945, la documentación ha sido bastante consistente.
Se celebra el trabajo en GPUs de núcleo abierto.
Hay otro proyecto de GPU de código abierto llamado NyuziProcessor. (https://github.com/jbush001/NyuziProcessor)
Quiero entrar al mundo de los FPGA, pero es difícil saber por dónde empezar y el campo en sí se siente intimidante.
El objetivo final es crear una tarjeta aceleradora para LLM (Large Language Model). Salvo por la parte de offloading de memoria, habría muchas similitudes con este proyecto.
Se pregunta por qué se mezclan operadores de asignación non-blocking y blocking en bloques
alwayssecuenciales.Hace tiempo hice algo parecido en VHDL. Había un sitio llamado opencores con varios proyectos HDL de código abierto. Me pregunto si hoy existe algún simulador HDL distribuido a gran escala, a nivel HPC. Tiene sentido usar GPUs modernas para hacer simulación a nivel RTL.
Me gusta ver proyectos de hardware abiertos. Pero se podría decir que esto es un coprocesador SIMD. Para ser una GPU, debería tener al menos algún tipo de salida de pantalla. Últimamente, como Nvidia y otros venden variantes solo para servidor de arquitecturas gráficas como GPU, el término se ha relajado un poco, pero la parte “gráfica” del diseño de una GPU sigue representando una parte importante de la complejidad.
Me pregunto si es común que una ALU implemente directamente la instrucción DIV a nivel de hardware. Quisiera saber si eso se usa como instrucción real en algo como un núcleo CUDA moderno, o si normalmente se emula por software. Un circuito real de división ocupa mucho espacio, así que no lo esperaba en una ALU de GPU. En Verilog es fácil escribir
DIV: begin alu_out_reg <= rs / rt; end, pero en silicio ocupa bastante espacio. Sin embargo, alguien que solo simula Verilog podría no darse cuenta de eso.Otra “GPU” que no ofrece funciones gráficas. Opinan que estas cosas deberían llamarse de otra manera.
Se simplificó asumiendo que los hilos se procesan en paralelo y que, después de cada instrucción, todos “convergen” al mismo contador de programa. En una GPU real, los hilos individuales pueden bifurcarse hacia distintos PC, lo que provoca branch divergence. Sería bueno probar primero la programación de GPU antes de fabricar una GPU en silicio. Ni siquiera es SIMD. (La misma persona que armó un circuito que hace parpadear un LED y dijo que había construido una CPU)