Die Schicht unter dem Serving-Stack. Jede Modelloperation läuft am Ende als GPU-Kernel, und die Kernelqualität entscheidet, wie viel der bezahlten Hardware tatsächlich genutzt wird. Sie schreiben selten selbst Kernel, doch diese Schicht zu lesen erklärt, warum sich die Systeme darüber so verhalten, wie sie es tun.
Wie eine GPU Arbeit ausführt
Ausführungsmodell
GPUs führen Tausende Threads in gleichgeschalteten Gruppen (Warps) aus, organisiert in Blöcken und auf Streaming-Multiprozessoren eingeplant. Threads eines Warps teilen sich einen Instruktionsstrom, daher serialisieren divergente Verzweigungen und verschwenden Lanes. Genug residente Warps pro SM zu halten (Occupancy) ist das, was Speicherlatenz verbirgt.
Speicherhierarchie
Register, dann kleiner schneller On-Chip-Shared-Memory und Caches, dann großer Off-Chip-HBM. Die Bandbreitenlücke zwischen On-Chip- und Off-Chip-Speicher beträgt Größenordnungen, deshalb ist Kernelleistung vor allem eine Frage davon, wie selten Daten diese Grenze überqueren und wie gut Zugriffe koaleszieren.
Tensor Cores
Dedizierte Einheiten für Matrix-Multiplikation-Akkumulation liefern den Großteil der FLOPS einer modernen GPU, bei reduzierten Präzisionen (FP16/BF16, FP8, INT8). Kernel, die Tensor Cores nicht auslasten oder Präzisionen nutzen, die die Hardware nicht kennt, lassen den größten Teil des Chips ungenutzt.
Rechenlimitiert oder speicherlimitiert
Jeder Kernel wird durch arithmetischen Durchsatz oder durch Speicherbandbreite begrenzt, je nachdem, was zuerst ausgeht. LLM-Prefill ist rechenlastig; Decode ist bandbreitenlastig. Zu wissen, auf welcher Seite der Linie eine Operation liegt, sagt Ihnen, ob mehr FLOPS oder weniger Datenbewegung hilft.
Was Kerneloptimierung tatsächlich bewirkt
Fusion: benachbarte Operationen (Matmul + Bias + Aktivierung, Teilschritte der Attention) zu einem Kernel verschmelzen, damit Zwischenergebnisse auf dem Chip bleiben statt über HBM hin und her zu wandern, und der Startaufwand je Kernel entfällt.
Tiling: Daten in Blöcken verarbeiten, die auf den Shared Memory zugeschnitten sind, sodass jede geladene Kachel vor der Verdrängung vielfach wiederverwendet wird.
Layout und Präzision: Tensoren für koaleszierte Zugriffe anordnen und Präzisionen wählen, die die Tensor Cores nativ ausführen.
Die Hotspots bei LLMs: Kernel für Matrixmultiplikation, Attention, Normalisierung und Aktivierung dominieren; eine Serving-Engine ist in erster Näherung ein Scheduler um eine Handvoll solcher Kernel herum.
Kernelarbeit ergänzt die Systemebene: Continuous Batching oder Prefix Caching ändern, welche Arbeit getan wird; Kernel ändern, wie schnell jede Arbeitseinheit läuft. Für Ersteres siehe Serving-Optimierung.
FlashAttention, das kanonische Beispiel
Standard-Attention materialisiert eine N x N große Score-Matrix im HBM, deshalb wächst der Speicherverkehr quadratisch mit der Sequenzlänge und die Operation wird bandbreitenlimitiert. FlashAttention strukturiert die Berechnung um: Sie streamt Kacheln der Query-, Key- und Value-Matrizen durch den On-Chip-Speicher, führt die Softmax-Normalisierung inkrementell mit den eintreffenden Kacheln fort und schreibt die vollständige Score-Matrix nie. Gleiches mathematisches Ergebnis, ein Bruchteil des Speicherverkehrs, und genau das machte Serving mit langem Kontext praktikabel.
Nachfolgende Versionen wurden für jede Hardwaregeneration neu abgestimmt (bessere Arbeitsaufteilung, asynchrone Tensor-Core-Pipelines, Pfade mit niedriger Präzision), und die Technik steckt heute in PyTorch und jeder großen Serving-Engine. Die Lehre lässt sich verallgemeinern: Die größten Kernelgewinne stammen daraus, die Berechnung um die Speicherhierarchie herum umzubauen, nicht aus dem Mikrotuning von Instruktionen.
Die Werkzeugleiter
Geordnet nach steigender Kontrolle und steigenden Kosten. Beginnen Sie oben; steigen Sie nur ab, wenn Profiling zeigt, dass die Ebene darüber nicht ausreicht.
1. HerstellerbibliothekencuBLAS, cuDNN und Verwandte: pro Architektur vorabgestimmte Standardoperationen. Hervorragend in ihrem Umfang; keine Fusion über Operationen hinweg, und NVIDIA-spezifisch.
2. Compilertorch.compile, XLA, TVM: Sie nehmen den Modellgraphen und erzeugen automatisch fusionierte, abgestimmte Kernel. Große Gewinne bei geringem Aufwand für Standardarchitekturen; neuartige Operationen können vom schnellen Pfad fallen.
3. Kernel-DSLsTriton und Ähnliches: eigene Kernel in einer Python-nahen Sprache auf Kachelebene schreiben, während der Compiler die Details der unteren Ebene übernimmt. Der Sweet Spot für eigene Attention-Varianten und fusionierte Operationen ohne volle CUDA-Expertise.
4. Handgeschriebene KernelCUDA (oder ROCm) mit expliziter Kontrolle über Speicher und Warps, so wie FlashAttention selbst gebaut ist. Höchste Leistung, hohe Expertise, echte Wartungslast, Hardwarebindung.
5. Portabilitäts-StacksNeuere Ökosysteme (zum Beispiel Mojo/MAX und andere MLIR-basierte Ansätze) zielen auf eine Kernel-Codebasis über Hersteller hinweg; wägen Sie ihre Reife gegen die Bindung ab, die sie beseitigen.
Entscheidungsgrundlagen: wie standardisiert Ihre Operatoren sind, was Spitzenleistung wert ist, welche Hardware Sie unterstützen müssen und ob die Stärke Ihres Teams bei Compilern oder bei Kerneln liegt. Profilieren Sie zuerst; der Engpass liegt oft nicht dort, wo die Intuition hinzeigt.