CUDA

Grafikkarten haben tausende kleine Rechenkerne, die eigentlich Bilder berechnen. Mit einer speziellen Software lassen sich diese Kerne für beliebige Rechenaufgaben nutzen. Diese Software heißt CUDA und stammt von NVIDIA.

CUDA steht für Compute Unified Device Architecture. Die Plattform macht die parallelen Rechenkerne von NVIDIA-Grafikkarten für allgemeine Berechnungen zugänglich. Seit der Veröffentlichung 2007 hat sich CUDA zur zentralen Infrastruktur für maschinelles Lernen und wissenschaftliches Rechnen auf GPUs entwickelt.

Warum Grafikkarten rechnen können

Eine CPU besitzt wenige, aber leistungsstarke Kerne. Eine GPU besitzt tausende kleinere Kerne, die für parallele Aufgaben optimiert sind. Ursprünglich berechnen diese Kerne Farbwerte von Bildpunkten. Viele wissenschaftliche und technische Probleme lassen sich aber in ähnlich parallele Teilaufgaben zerlegen.

Beispiel: Eine Matrixmultiplikation mit 4096 × 4096 Elementen lässt sich in tausende unabhängige Teilberechnungen zerlegen. Auf einer CPU mit 16 Kernen laufen 16 Berechnungen gleichzeitig. Auf einer GPU mit 10.000 Kernen laufen entsprechend mehr Berechnungen parallel.

Beispiel: Beim Training eines neuronalen Netzes müssen in jedem Schritt Millionen von Gewichten aktualisiert werden. Jede Aktualisierung ist mathematisch unabhängig von den anderen. GPUs können diese Aktualisierungen gleichzeitig durchführen.

CUDA öffnet diese parallele Rechenkapazität für beliebige Programme. Ohne CUDA (oder vergleichbare Plattformen) bleibt die GPU auf Grafikberechnungen beschränkt.

Fachliche Einordnung: Die Architektur von GPUs folgt dem SIMT-Prinzip (Single Instruction, Multiple Threads). Dabei führen viele Threads dieselbe Instruktion auf unterschiedlichen Daten aus. Dieses Modell eignet sich besonders für datenparallele Algorithmen, wie sie in der linearen Algebra und im Deep Learning vorkommen.

Das CUDA-Programmiermodell

CUDA erweitert die Programmiersprache C/C++ um spezielle Konstrukte. Ein Programm besteht aus Host-Code (läuft auf der CPU) und Device-Code (läuft auf der GPU). Der Device-Code wird in sogenannten Kernels organisiert.

Ein Kernel ist eine Funktion, die von vielen Threads gleichzeitig ausgeführt wird. Die Threads sind in Blöcke gruppiert, die Blöcke bilden ein Grid. Diese Hierarchie erlaubt es, Millionen von Threads zu starten und auf die GPU-Kerne zu verteilen.

Beispiel: Ein Kernel addiert zwei Vektoren mit je einer Million Elementen. Jeder Thread addiert genau ein Elementpaar. Der Programmierer startet eine Million Threads, die GPU verteilt diese auf ihre Kerne.

Beispiel: Bei der Berechnung eines Embeddings wird ein Eingabetext in einen numerischen Vektor umgewandelt. Die Matrix-Vektor-Multiplikation, die dabei stattfindet, wird als CUDA-Kernel auf der GPU ausgeführt.

Host (CPU)Programmsteuerung
DatentransferHost ↔ Device
GridAlle Blöcke
Block 0256 Threads
Block 1256 Threads
Block N256 Threads

Speicherhierarchie

CUDA-Programme arbeiten mit mehreren Speicherebenen. Jeder Thread hat eigene Register. Threads innerhalb eines Blocks teilen sich Shared Memory (schnell, aber klein). Alle Threads können auf den globalen GPU-Speicher zugreifen (groß, aber langsamer).

Beispiel: Eine Convolution-Operation in einem Bilderkennungsmodell lädt einen Bildausschnitt in den Shared Memory. Alle Threads im Block greifen auf denselben Ausschnitt zu, ohne ihn einzeln aus dem globalen Speicher laden zu müssen. Das reduziert die Zugriffszeit erheblich.

Das CUDA-Ökosystem

CUDA ist nicht nur ein Programmiermodell. Es umfasst ein ganzes Ökosystem aus Werkzeugen und Bibliotheken.

CUDA Toolkit

Das Toolkit enthält den nvcc-Compiler, der CUDA-C++-Code in GPU-Maschinencode übersetzt. Dazu kommen Debugging-Werkzeuge (cuda-gdb), Profiler (Nsight Systems, Nsight Compute) und Dokumentation.

Spezialisierte Bibliotheken

NVIDIA stellt optimierte Bibliotheken bereit, die CUDA intern nutzen:

Beispiel: PyTorch ruft beim Training intern cuBLAS für Matrixmultiplikationen und cuDNN für Schichten wie Convolution auf. Der Anwender schreibt Python-Code, die GPU-Beschleunigung geschieht transparent über diese Bibliotheken.

CUDA im maschinellen Lernen

Die Bedeutung von CUDA für maschinelles Lernen ist schwer zu überschätzen. Praktisch alle großen ML-Frameworks nutzen CUDA als primäre GPU-Schnittstelle.

Beispiel: Das Training eines Transformer-Modells mit mehreren Milliarden Parametern dauert auf CPUs Monate bis Jahre. Mit CUDA-beschleunigten GPUs reduziert sich die Trainingszeit auf Tage bis Wochen. Die Matrixoperationen in den Attention-Schichten profitieren direkt von der Parallelisierung.

Beispiel: Backpropagation berechnet Gradienten für jedes Gewicht im Netz. Bei einem Modell mit 7 Milliarden Gewichten fallen in jedem Trainingsschritt 7 Milliarden Gradientenberechnungen an. CUDA verteilt diese Berechnungen auf tausende GPU-Kerne.

Typischer Ablauf beim Training

Daten werden vom Hauptspeicher in den GPU-Speicher kopiert. CUDA-Kernels führen den Forward-Pass durch. Anschließend berechnen weitere Kernels die Gradienten im Backward-Pass. Die aktualisierten Gewichte bleiben im GPU-Speicher für den nächsten Schritt. Nur Ergebnisse und Checkpoints werden zurück in den Hauptspeicher kopiert.

Beispiel: Bei einem Training mit Batch Size 32 und einer Sequenzlänge von 2048 Token verarbeitet die GPU in jedem Schritt eine Matrix mit 32 × 2048 Einträgen. Der gesamte Forward- und Backward-Pass bleibt auf der GPU. Nur der Verlust-Wert wird an die CPU zurückgegeben.

CUDA-Versionen und Kompatibilität

CUDA existiert in zwei Versionsdimensionen: der Toolkit-Version und der Compute Capability der GPU-Hardware.

Die Toolkit-Version (z.B. CUDA 12.4) bestimmt, welche Sprachfeatures und Bibliotheken verfügbar sind. Die Compute Capability (z.B. 8.9 für Ada Lovelace, 9.0 für Hopper) beschreibt, welche Hardware-Funktionen die GPU unterstützt.

Beispiel: Ein PyTorch-Modell, das mit CUDA 11.8 kompiliert wurde, läuft nicht mit einem CUDA-12.x-Treiber, wenn die Bibliotheken nicht kompatibel sind. In der Praxis ist die Abstimmung zwischen Framework-Version, CUDA-Toolkit und GPU-Treiber eine häufige Fehlerquelle.

Neuere GPU-Generationen bringen neue Compute Capabilities und damit neue Funktionen. Tensor Cores (ab Volta, Compute Capability 7.0) beschleunigen Matrix-Operationen in gemischter Präzision. Transformer Engines (ab Hopper, 9.0) optimieren speziell Attention-Berechnungen in Transformer-Architekturen.

Alternativen und Wettbewerb

CUDA ist nicht die einzige Plattform für GPU-Computing. Alternativen existieren, haben aber unterschiedliche Verbreitung und Reifegrade.

OpenCL ist ein offener Standard, der auf GPUs verschiedener Hersteller läuft. Die Performance liegt bei vergleichbaren Aufgaben typischerweise unter der von CUDA, weil herstellerspezifische Optimierungen fehlen.

AMD bietet mit ROCm eine eigene Plattform an. ROCm unterstützt einen Teil der CUDA-API über eine Kompatibilitätsschicht (HIP). Die Bibliotheksabdeckung wächst, erreicht aber nicht den Umfang des CUDA-Ökosystems.

Apple nutzt mit Metal ein eigenes Framework für GPU-Berechnungen auf M-Chips. PyTorch unterstützt Metal über das MPS-Backend. Die Performance liegt bei ML-Aufgaben unter vergleichbaren NVIDIA-GPUs.

Beispiel: Ein Forschungsteam möchte ein Modell auf AMD-Hardware mit ROCm trainieren. Die Forward-Pass-Berechnung funktioniert, aber eine spezialisierte Operation aus cuDNN hat kein ROCm-Äquivalent. Das Team muss die Operation manuell implementieren oder auf NVIDIA-Hardware ausweichen.

Fachliche Einordnung: Die Dominanz von CUDA im ML-Bereich ist nicht nur technisch bedingt. Das Ökosystem profitiert von einem Netzwerkeffekt: Entwickler optimieren für CUDA, weil die meisten GPUs NVIDIA sind. Nutzer kaufen NVIDIA, weil die Software dafür optimiert ist. Dieser Lock-in ist aus wettbewerbsrechtlicher und strategischer Sicht relevant.

Grenzen und Einschränkungen

CUDA unterliegt mehreren strukturellen Beschränkungen, die bei der Planung von ML-Projekten relevant sind.

GPU-Speicher ist begrenzt. Eine NVIDIA A100 bietet 40 oder 80 GB. Ein Modell mit 70 Milliarden Parametern in 16-Bit-Präzision benötigt allein für die Gewichte 140 GB. Techniken wie Modellparallelismus, Quantisierung und Offloading adressieren dieses Problem, erhöhen aber die Komplexität.

Beispiel: Beim Fine-Tuning eines 13-Milliarden-Parameter-Modells reicht der Speicher einer einzelnen GPU mit 24 GB nicht aus. Neben den Gewichten müssen Gradienten und Optimizer-Zustände im Speicher gehalten werden. LoRA reduziert den Speicherbedarf, indem nur wenige zusätzliche Parameter trainiert werden.

Der Datentransfer zwischen CPU-Hauptspeicher und GPU-Speicher ist ein Engpass. Die PCIe-Schnittstelle liefert maximal 64 GB/s (PCIe 5.0 x16). Wenn Daten schneller verarbeitet als nachgeliefert werden, wartet die GPU auf neue Eingaben.

CUDA-Programme sind nicht portabel. Code, der für NVIDIA-GPUs geschrieben wurde, läuft nicht auf AMD- oder Intel-GPUs. Wer CUDA nutzt, bindet sich an NVIDIA-Hardware.

Die Fehlersuche in CUDA-Programmen ist aufwändiger als bei CPU-Code. Race Conditions zwischen tausenden Threads, Speicherzugriffsfehler auf der GPU und asynchrone Ausführung erschweren das Debugging.

Fachliche Einordnung: Die Abhängigkeit von CUDA und NVIDIA-Hardware wird in der Industrie als "CUDA-Moat" bezeichnet. Trotz wachsender Alternativen bleibt CUDA der de-facto-Standard. Für produktive ML-Systeme ist die Wahl der GPU-Plattform eine Architekturentscheidung mit langfristigen Konsequenzen für Kosten, Verfügbarkeit und Flexibilität.


Karl Kratz · 15.02.2025 (aktualisiert 15.03.2026)

Technologie Hardware Grafikkarten