AMD-GPU-Debugger
(thegeeko.me)- Ausgehend vom Fehlen eines Debuggers, der die GPU-Ausführung stoppen und den Zustand untersuchen kann, beschreibt der Beitrag, wie diese Funktion direkt auf AMD-GPUs implementiert wird
- Über die DRM-Schnittstelle und libdrm erfolgt die direkte Kommunikation mit der GPU, wobei Kontext-Erstellung, Pufferzuweisung und Befehlsübermittlung schrittweise aufgebaut werden
- Mit den TBA/TMA-Registern und dem Trap-Handler wird die GPU-Ausführung angehalten und über die Synchronisierung mit der CPU wird das Lesen sowie die Wiederherstellung des Zustands realisiert
- Durch SPIR-V-Codekompilierung und RADV-Integration wird die reale Shader-Debugging-Umgebung erweitert und die Implementierung von breakpoint·stepping·watchpoint ermöglicht
- Dieser Ansatz, der die interne Struktur der GPU direkt steuert, zeigt die Machbarkeit eines vollständigen Debuggers für AMD-GPUs und lässt Raum für eine Weiterentwicklung hin zur Vulkan-Integration
Notwendigkeit und Ansatz beim GPU-Debugging
- Ausgangspunkt ist der Mangel an einem Werkzeug, mit dem sich die GPU-Ausführung wie bei der CPU anhalten und den Zustand prüfen lässt
- Das parallele Ausführungsmodell der GPU macht das Debugging deutlich komplexer
- In der AMD ROCm-Umgebung existiert
rocgdb, unterstützt jedoch nur einen auf ROCm begrenzten Bereich - Basierend auf der Blog-Serie von Marcell Kiss wurde der Versuch unternommen, einen Debugger zu implementieren, der direkt mit der GPU kommuniziert
Direkte Kommunikation mit der GPU
- Die Funktionsweise des RADV-Treibers wurde analysiert, um zu lernen, wie man direkt mit der GPU kommuniziert
- Nach dem Öffnen von
/dev/dri/cardXwird mit dem KMD (Kernel Mode Driver) verbunden und anschließendamdgpu_device_initializeaufgerufen - Mit
libdrmwerden Kontext-Erstellung (amdgpu_cs_ctx_create) und Pufferzuweisung durchgeführt- Es werden zwei Puffer erzeugt: ein Codepuffer und ein Befehls-Puffer
- Die Puffer werden in den virtuellen Adressraum von GPU und CPU gemappt
- Das Mapping wird nicht mehr über
amdgpu_bo_va_op, sondern über direkte IOCTL-Aufrufe abgewickelt
- Das Mapping wird nicht mehr über
- Mit
clangundobjdumpwird Shader-Assembliercode kompiliert und das Binary extrahiert - Die GPU-Befehle werden im
PM4 Packet-Format aufgebaut, um den Shader-Ausführungsbefehl zu senden
GPU-Traps und Debugfs-Nutzung
- Der Trap-Handler wird über die RDNA3-ISA-TBA/TMA-Register eingerichtet
TBA: Adresse des Trap-HandersTMA: temporäre Speicheradresse für den Trap-Handler
- Da aus dem Userspace kein direkter Zugriff möglich ist, wird die debugfs-Schnittstelle verwendet
- Registerzugriff erfolgt über die Datei
/sys/kernel/debug/dri/{PCI address}/regs2 - Register-Schreibzugriffe mit
amdgpu_debugfs_regs2_write
- Registerzugriff erfolgt über die Datei
- Mit je einem VMID werden TBA/TMA gesetzt, um den Trap-Handler zu aktivieren
- Jede VMID unterscheidet einen GPU-Prozesskontext
Implementierung des Trap-Handlers
- Der Trap-Handler ist ein privilegiertes Shader-Programm, das ausgeführt wird, wenn die GPU auf eine Ausnahme trifft
- Über das TTMP-Register werden GPU-Zustände (STATUS, EXEC, VCC usw.) gespeichert
- Mit dem Befehl
global_store_addtid_b32werden Thread-spezifische Registerwerte im Speicher gespeichert - Erkennt die CPU, dass die GPU Daten geschrieben hat, wird die GPU mit dem
SQ_CMD-Register kurz angehalten- Danach analysiert die CPU die Daten und setzt anschließend mit
SQ_CMDdie GPU-Ausführung wieder in Gang
- Danach analysiert die CPU die Daten und setzt anschließend mit
- Beim Verlassen des Handlers werden Programmzähler und Registerzustand wiederhergestellt
SPIR-V-Codeausführung und RADV-Integration
- Statt manueller Assembly wird die Kompilierung von SPIR-V-Code unterstützt
- Das
ACO-Modul von RADV konvertiert SPIR-V in ein GPU-Binary - Mit der Umgebungsvariable
RADV_FORCE_FAMILYwird ein virtuelles Gerät erzeugt
- Das
- Im
null_winsys-Modus von RADV wird nur kompiliert, ohne physischen Hardwarezugriff - Aus dem Kompilat werden Shader-Code, Ressourcenkonfiguration und Debug-Informationen extrahiert
Erweiterung der Debugger-Funktionen
- Stepping: Mit den Bits
RSRC1.DEBUG_MODEundRSRC3.TRAP_ON_STARTwird die Befehl für Befehl-Ausführung gesteuert - Breakpoints: Nach der Berechnung der Programmzählerposition auf Basis der Codepufferadresse erfolgt die Trap-Verarbeitung
- Source Mapping: Mithilfe der Debug-Informationen des ACO-Compilers erfolgt das Mapping der Source-Code-Zeilen
- Watchpoints: Mittels GPU-Seiten-Schutz oder des
SQ_WATCH-Registers ist eine Adressüberwachung möglich - Variablennamen- und Typ-Nachverfolgung: In der NIR-Optimierungsstufe von Mesa ist eine verbesserte Weitergabe von Debug-Informationen erforderlich
- Vulkan-Integration: Auf Basis von RADV ist Frame-basiertes Debugging mit Puffer-, Textur- und Konstanteninformationen möglich
Bonus: Page-Walking-Code im User Mode
- Ein Beispielcode für Page-Table-Walk-Code für RDNA3 (gfx11)-GPUs wird bereitgestellt
- Mit enthaltenen PDE/PTE-Strukturdefinitionen und Dekodierfunktionen
- mit implementiertem Prozess der Umwandlung einer virtuellen in eine physische Adresse
- Durch das Lesen der Seitentabellenregister pro VMID ist eine Analyse der GPU-Memory-Mapping-Struktur möglich
Fazit
- Es wird die Machbarkeit einer vollständigen Debugger-Implementierung über Zugriff auf Kernel- und Hardwareebene auf AMD GPUs nachgewiesen
- Durch den Aufbau einer bidirektionalen Kommunikationsschleife zwischen CPU und GPU wird das Unterbrechen, die Zustandsanalyse und das Fortsetzen während der Ausführung realisiert
- Mit zukünftiger RADV- und Vulkan-Integration besteht Potenzial für den weiteren Ausbau zu einer entwicklerfreundlichen GPU-Debugging-Umgebung
1 Kommentare
Hacker-News-Kommentare
Zwar nicht AMD, aber Metal bietet wirklich hervorragende Debugger und Entwicklungs-Tools
Deshalb nutze ich bei GPU-Arbeit immer zuerst Metal und portiere es danach auf andere Systeme
Die Metal-Debugger-Dokumentation ist einen Blick wert
Ich bin zwar kein AAA-Spieleentwickler, aber für meine Zwecke war es nahezu perfekt
Besonders beeindruckend ist die Funktion, formatierte Log-Strings aus Shadern auszugeben, die dann zusammen mit den App-Logs angezeigt werden
Ich entwickle gerade eine GPU-basierte App, die sowohl Metal als auch OpenGL verwendet, und auf der OpenGL-Seite war es schwer, Tools auf Metal-Niveau zu finden
Beide Plattformen bieten eigene Debugger, und deren Qualität war ziemlich gut
Am Ende habe ich verstanden, dass Tooling alles ist, wenn man nur noch einen schwarzen Bildschirm sieht
Ich frage mich, ob man unter Windows bessere Tools bekommt, wenn man statt OpenGL DirectX verwendet
Vor allem beim Umgang mit Compute Shadern funktioniert das Profiling häufig nicht gut
Es wirkt wie ein Tool, das primär für Grafik entwickelt wurde und bei KI oder großen Buffer-Arbeitslasten noch Grenzen hat
Für mich passte sie viel besser als OpenGL
Hast du auf der OpenGL-Seite schon RenderDoc ausprobiert? Für Vulkan/OpenGL ist das das ähnlichste Tool
Einen teuren Computer zu kaufen, um eine Metal-exklusive API zu debuggen, ist ineffizient
Wenn man ernsthaft Grafikprogrammierung lernen will, ist es meiner Meinung nach besser, unter Windows oder Linux DX12 oder Vulkan zu lernen
Mit Tools wie RenderDoc geht das gut genug
Metal ist eine gute API, aber seine größte Einschränkung ist, dass es außerhalb der Apple-Plattformen nicht nutzbar ist
In Server- oder Spieleumgebungen werden meist AMD- oder Nvidia-GPUs verwendet, daher ist eine Metal-zentrierte Entwicklung nicht besonders praktikabel
Für NVIDIA CUDA gibt es mit cuda-gdb ein First-Party-GDB
Wie die offizielle Dokumentation zeigt, passt es gut zum Thread-Modell von CUDA
Allerdings ist Single-Stepping nur auf Warp-Ebene möglich
Auf NVIDIA-Karten kann man NSight verwenden, und es gibt außerdem RenderDoc, das auf verschiedenen GPUs funktioniert
Wenn High-Level-Visualisierungen wie QML oder QSG_VISUALIZE=overdraw fehlen, ist es interessant, eine Szene auf API-Call-Ebene nachzuverfolgen
Viele wissen nicht, dass man sie auch ohne GPU verwenden kann
Auf die Frage, ob es offizielle Tools für AMD gibt: GDB unterstützt AMD-GPU-Debugging
Außerdem gibt es Tools wie AMDs UMR,
Radeon GPU Detective und die
Radeon Developer Tool Suite
Hier ist ein selbst gebautes Monitoring-Tool für AMD-GPUs
Es handelt sich um das Projekt picomon, das ich gebaut habe, um das Problem zu lösen, dass nvtop zu strikt ist und deshalb oft abstürzt
Für jede Plattform gibt es eigene Tools, etwa für Metal, CUDA, Pix oder PS/Switch
Auch deshalb bevorzugen Forschende noch immer CUDA
Nsight Systems ist eines davon
Mich würde interessieren, ob jemand eine 7900 XTX GPU für lokale Inferenz oder Diffusion verwendet
Ich habe Linux installiert, aber die Karte liegt die meiste Zeit brach, also würde ich sie gern sinnvoll nutzen
Früher gab es Probleme rund um Python, aber inzwischen ist es stabil genug, dass sogar img2video möglich ist
Gemessen an 24 GB VRAM ist sie meiner Meinung nach weiterhin die Karte mit dem besten Preis-Leistungs-Verhältnis
ROCm wurde kürzlich für UX-Verbesserungen umfassend überarbeitet, daher lohnt sich ein Blick auf TheRock
Auch das Modell devstral:24b lief ziemlich schnell
In ComfyUI funktionierte das meiste gut, aber bei ungewöhnlicheren Aufgaben war es instabil
Inzwischen soll es stabiler geworden sein