- Parte de la ausencia de un depurador capaz de pausar la ejecución de la GPU e inspeccionar su estado, y explica el proceso de implementarlo directamente sobre una GPU de AMD
- Se comunica directamente con la GPU mediante la interfaz DRM y libdrm, construyendo paso a paso el proceso de creación de contexto, asignación de búferes y envío de comandos
- Aprovecha los registros TBA/TMA y un trap handler para detener la ejecución de la GPU, y construye una arquitectura para leer y restaurar el estado mediante sincronización con la CPU
- Amplía el entorno real de depuración de shaders mediante la compilación de código SPIR-V y la integración con RADV, haciendo posible implementar funciones de breakpoint, stepping y watchpoint
- Este enfoque, que controla directamente la estructura interna de la GPU, demuestra la posibilidad de implementar un depurador completo para GPUs AMD, con margen de evolución futura hacia la integración con Vulkan
La necesidad de depurar GPU y el enfoque
- Parte de la falta de herramientas para pausar la ejecución de la GPU e inspeccionar su estado, como se hace en CPU
- El modelo de ejecución paralela de la GPU hace que la depuración sea mucho más compleja
- Existe
rocgdb en el entorno AMD ROCm, pero solo admite un alcance limitado a ROCm
- Tomando como referencia la serie de blogs de Marcell Kiss, se intenta implementar un depurador que se comunique directamente con la GPU
Comunicación directa con la GPU
- Se aprende a comunicarse directamente con la GPU siguiendo el funcionamiento del driver RADV
- Se abre
/dev/dri/cardX para conectarse con el KMD (driver en modo kernel) y luego se llama a amdgpu_device_initialize
- Mediante
libdrm se realiza la creación de contexto (amdgpu_cs_ctx_create) y la asignación de búferes
- Se crean dos búferes: uno de código y otro de comandos
- Los búferes se mapean al espacio de direcciones virtuales de GPU/CPU
- En lugar de
amdgpu_bo_va_op, el mapeo se resuelve con llamadas directas a IOCTL
- Con
clang y objdump se compila el código ensamblador del shader y se extrae el binario
- Se construyen comandos de GPU en formato PM4 Packet para enviar la orden de ejecutar el shader
Traps de GPU y uso de Debugfs
- Se configuran trap handlers usando los registros TBA/TMA de la ISA RDNA3
TBA: dirección del trap handler
TMA: dirección de memoria temporal para el trap handler
- Como no se puede acceder directamente desde espacio de usuario, se utiliza la interfaz debugfs
- Se accede a los registros a través del archivo
/sys/kernel/debug/dri/{PCI address}/regs2
- La escritura en registros se realiza con
amdgpu_debugfs_regs2_write
- Se configuran TBA/TMA por VMID para activar el trap handler
- Cada VMID distingue un contexto de proceso de GPU
Implementación del trap handler
- El trap handler es un programa de shader privilegiado que se ejecuta cuando la GPU encuentra una excepción
- Usa registros TTMP para guardar el estado de la GPU (STATUS, EXEC, VCC, etc.)
- La instrucción
global_store_addtid_b32 se usa para guardar en memoria los valores de registros por hilo
- Cuando la GPU escribe los datos, la CPU lo detecta y pausa temporalmente la GPU con el registro SQ_CMD
- Después de analizar los datos, la CPU vuelve a usar
SQ_CMD para reanudar la ejecución de la GPU
- Al regresar, el trap handler restaura el contador de programa y el estado de los registros
Ejecución de código SPIR-V e integración con RADV
- Se añade soporte para compilar código SPIR-V en lugar de ensamblado manual
- Se usa el compilador
ACO de RADV para convertir SPIR-V en binario de GPU
- La variable de entorno
RADV_FORCE_FAMILY permite crear un dispositivo virtual
- El modo
null_winsys de RADV permite compilar sin acceder al hardware real
- Del resultado de la compilación se extraen código de shader, configuración de recursos e información de depuración
Ampliación de funciones del depurador
- Stepping: se controla la ejecución por instrucción usando los bits
RSRC1.DEBUG_MODE y RSRC3.TRAP_ON_START
- Breakpoints: se calcula la posición del contador de programa a partir de la dirección del búfer de código y luego se procesa el trap
- Source Mapping: se mapean líneas del código fuente usando la información de depuración del compilador ACO
- Watchpoints: es posible implementar vigilancia de direcciones mediante protección de páginas de GPU o el registro
SQ_WATCH
- Seguimiento de nombres y tipos de variables: en la fase de optimización NIR de Mesa, hace falta mejorar la propagación de información de depuración
- Integración con Vulkan: sobre la base de RADV, puede habilitarse depuración por frame y aprovechar información de búferes, texturas y constantes
Bonus: código de page walking en modo usuario
- Se ofrece un ejemplo de código de recorrido de tablas de páginas para GPU RDNA3 (gfx11)
- Incluye definiciones de estructuras PDE/PTE y funciones de decodificación
- Implementa el proceso de convertir direcciones virtuales en físicas
- Al leer los registros de tablas de páginas por VMID, se puede analizar la estructura de mapeo de memoria de la GPU
Conclusión
- Se demuestra la posibilidad de implementar un depurador completo para GPU AMD mediante acceso a nivel de kernel y hardware
- Se construye un bucle de comunicación bidireccional entre CPU y GPU para pausar la ejecución, analizar el estado y reanudarla
- En el futuro, la integración con RADV y Vulkan podría convertirlo en un entorno de depuración de GPU más amigable para desarrolladores
1 comentarios
Opiniones en Hacker News
No es AMD, pero Metal ofrece un debugger y un conjunto de herramientas de desarrollo realmente excelentes
Por eso, cuando trabajo con GPU, siempre prefiero usar primero Metal y luego portar a otros sistemas
Vale la pena consultar la documentación de Metal Debugger
No soy desarrollador de juegos AAA, pero para mi uso fue casi perfecto
En especial, me sorprendió la función que permite imprimir cadenas de log con formato desde los shaders y mostrarlas mezcladas con los logs de la app
Estoy desarrollando una app basada en GPU que usa tanto Metal como OpenGL, y del lado de OpenGL fue difícil encontrar herramientas al nivel de Metal
Ambas plataformas ofrecen debuggers dedicados, y la calidad era bastante buena
Al final entendí que cuando solo ves una pantalla negra, las herramientas lo son todo
Me pregunto si usando DirectX en lugar de OpenGL se obtienen mejores herramientas en Windows
En especial, al trabajar con compute shader, muchas veces el profiling no funciona bien
Como es una herramienta diseñada con foco en gráficos, parece que todavía tiene limitaciones para IA o trabajo con buffers grandes
Me encajó mucho mejor que OpenGL
Del lado de OpenGL, ¿has probado RenderDoc? Es la herramienta más parecida para Vulkan/OpenGL
Comprar una computadora cara para hacer debugging de una API exclusiva de Metal es ineficiente
Si quieres aprender programación gráfica en serio, creo que es mejor aprender DX12 o Vulkan en Windows o Linux
Con herramientas como RenderDoc se puede perfectamente
Metal es una buena API, pero su mayor limitación es que no puede usarse fuera de las plataformas de Apple
En entornos de servidores o juegos, la mayoría usa GPU de AMD o Nvidia, así que un desarrollo centrado en Metal no es práctico
CUDA de NVIDIA tiene un GDB oficial llamado cuda-gdb
Como puede verse en la documentación oficial, está bien adaptado al modelo de hilos de CUDA
Eso sí, solo permite ejecutar paso a paso a nivel de warp
En tarjetas NVIDIA se puede usar NSight, y también está RenderDoc, que funciona con distintas GPU
Cuando faltan visualizaciones de alto nivel como QML o QSG_VISUALIZE=overdraw, es interesante rastrear la escena a nivel de llamadas de API
Mucha gente no sabe que pueden usarse incluso sin GPU
Ante la pregunta de si hay herramientas oficiales para AMD, GDB soporta debugging de AMD GPU
También existen herramientas como UMR de AMD,
Radeon GPU Detective y
Radeon Developer Tool Suite
Comparto una herramienta de monitoreo hecha por mí para AMD GPU
Es un proyecto llamado picomon, que hice para resolver el problema de que nvtop era demasiado estricto y se caía con frecuencia
Cada plataforma, como Metal, CUDA, Pix o PS/Switch, tiene sus propias herramientas dedicadas
Por eso los investigadores todavía tienden a preferir CUDA
Nsight Systems es una de ellas
Me pregunto si alguien usa una GPU 7900 XTX para inferencia local (inference) o diffusion
Instalé Linux, pero la mayor parte del tiempo está sin usarse y me gustaría aprovecharla
Antes había problemas relacionados con Python, pero recientemente se estabilizó y ya permite hasta img2video
Con 24GB de VRAM, sigo pensando que es la tarjeta con mejor relación precio-rendimiento
ROCm fue renovado a fondo recientemente para mejorar la UX, así que recomiendo revisar TheRock
El modelo devstral:24b también corría bastante rápido
En ComfyUI casi todo funcionaba bien, pero en tareas raras era inestable
He oído que recientemente se estabilizó