Wenn deiner GPU der VRAM ausgeht: Was du tun kannst
GPU-VRAM ist der Engpass bei KI- und Grafik-Workloads. So funktionieren Unified Memory, VRAM-Offloading und NVMe-Swapping wirklich.

Die häufigste Fehlermeldung beim maschinellen Lernen ist weder ein Python-Traceback noch eine Shape-Mismatch. Es ist CUDA out of memory. Dein Modell ist zu groß, deine Batch-Size zu hoch oder deine Zwischenaktivierungen passen nicht in den VRAM deiner GPU. Eine RTX 4090 hat 24 GB. Ein 70B-Parameter-Modell in halber Genauigkeit braucht ~140 GB. Die Rechnung geht nicht auf, und mehr Geld für größere GPUs verschiebt das Problem nur – eine H100 mit 80 GB kann die größten Modelle trotzdem nicht auf einer einzelnen Karte unterbringen.
Was wäre, wenn du den GPU-Speicher transparent mit System-RAM oder sogar einem NVMe-Speicher erweitern könntest? Tools wie NVIDIAs Greenboost und ähnliche Projekte machen genau das – sie nutzen die Speicherhierarchie (VRAM → System-RAM → SSD), um Workloads auszuführen, die eigentlich nicht auf deine Hardware passen sollten. Die Performance-Einbußen sind real, für viele Anwendungsfälle aber erstaunlich gut beherrschbar. Um zu verstehen, wie das funktioniert, muss man zuerst die GPU-Speicherhierarchie selbst verstehen.
Warum sich GPU-Speicher von CPU-Speicher unterscheidet
CPU- und GPU-Speicher dienen grundlegend unterschiedlichen Zugriffsmustern. CPU-Workloads sind latenzsensibel – ein einzelner Thread braucht ein Datenstück und blockiert, bis es ankommt. CPU-Caches sind darauf ausgelegt, die Latenz bei zufälligen Zugriffsmustern zu minimieren.
GPU-Workloads sind durchsatzorientiert – Tausende Threads brauchen jeweils ihre Daten, und die GPU kann zwischen Threads wechseln, um Latenz zu verstecken. GPU-Speicher (HBM bei Rechenzentrums-GPUs, GDDR bei Consumer-Karten) ist auf Bandbreite ausgelegt: Er liefert enorme Datenmengen pro Sekunde, auch wenn ein einzelner Zugriff länger dauert als ein Treffer im CPU-Cache.
Memory bandwidth comparison (approximate):
RTX 4090 GDDR6X: 1,000 GB/s
H100 HBM3: 3,350 GB/s
DDR5 System RAM: 50 GB/s
PCIe 5.0 x16: 64 GB/s (theoretical max)
NVMe SSD: 7 GB/s
The bandwidth cliff between VRAM and system RAM is ~20x.
Between VRAM and NVMe it's ~140x.
This is why naive offloading to system RAM kills performance —
you're trying to feed a 1,000 GB/s appetite through a 50 GB/s straw.
Genau diese Bandbreitenlücke ist der Grund, warum es nicht einfach funktioniert, GPU-Speicher ‚virtuell‘ zu machen – also Daten wie bei der CPU ins System-RAM auszulagern, so wie CPUs es mit der Festplatte tun. Eine CPU verkraftet Page Faults mit vielleicht einer zehnfachen Verlangsamung. Greift eine GPU statt auf VRAM auf System-RAM zu, sinkt die Bandbreite um den Faktor 20. Bei bandbreitenlimitierten Workloads (also den meisten ML-Inferenzen) bedeutet das eine 20-fache Verlangsamung.
So funktioniert VRAM-Offloading tatsächlich
Der Trick besteht nicht darin, System-RAM wie langsamen VRAM zu behandeln. Stattdessen werden Daten vorab aus dem System-RAM in den VRAM geladen, bevor die GPU sie braucht – die Latenz wird so hinter der Berechnung versteckt. Das ist der zentrale Gedanke hinter jeder praktischen Technik zur VRAM-Erweiterung.
Bei der Inferenz neuronaler Netze läuft die Berechnung sequentiell durch die Layer. Während die GPU Layer 5 verarbeitet, weiß sie, dass Layer 6 als Nächstes kommt. Ein kluges Offloading-System kann die Gewichte von Layer 6 bereits aus dem System-RAM in den VRAM übertragen, während Layer 5 noch rechnet. Dauert die Berechnung länger als der Transfer (bei großen Layern oft der Fall), wird der Transfer komplett versteckt – die GPU wartet nie.
# Conceptual overlap of compute and transfer
# (simplified pseudocode)
def inference_with_offloading(model, input_data):
# Only 2 layers fit in VRAM at a time
# Rest are in system RAM
for i, layer in enumerate(model.layers):
# Start async transfer of NEXT layer while computing current
if i + 1 < len(model.layers):
async_transfer_to_gpu(model.layers[i + 1])
# Compute on current layer (GPU is busy, transfer happens in parallel)
output = layer.forward(input_data)
# Evict current layer from VRAM (it's done)
transfer_to_ram(layer)
# Wait for next layer transfer to complete (usually already done)
sync_transfer()
input_data = output
return output
Dieser Pipeline-Ansatz funktioniert bei Inferenz gut, weil der Berechnungsgraph vorhersehbar ist – du weißt genau, welche Gewichte als Nächstes gebraucht werden. Training ist schwieriger, weil Backward-Passes Aktivierungen aus dem Forward-Pass benötigen, was deutlich komplexere Datenbewegungsmuster erzeugt.
Die Ansätze in der Praxis
CUDA Unified Memory
NVIDIAs CUDA Unified Memory schafft einen einzigen Adressraum, der sowohl den VRAM der GPU als auch das System-RAM umspannt. Die CUDA-Runtime verschiebt Seiten automatisch zwischen beiden, abhängig vom Zugriffsmuster. Greift die GPU auf eine Seite im System-RAM zu, löst das einen Page Fault aus, und die Seite wird in den VRAM migriert.
Der Vorteil: Für die Anwendung ist das vollkommen transparent. Dein CUDA-Code muss die Datenplatzierung nicht selbst verwalten. Der Nachteil: Page Faults sind teuer, und die Migrationsheuristiken der Runtime passen nicht immer zum Zugriffsmuster der Anwendung. Bei vorhersehbaren Workloads wie der Inferenz neuronaler Netze schlägt explizites Management die automatische Migration.
Layer-by-Layer-Offloading
Tools wie Hugging Face Accelerate, DeepSpeed ZeRO-Inference und das Flag --mmap von llama.cpp setzen explizites Layer-Offloading um. Sie halten nur die aktiven Layer im VRAM und streamen den Rest aus dem System-RAM oder von der Festplatte. Das Modell muss nicht komplett in den VRAM passen – es reicht, wenn ein oder zwei Layer gleichzeitig hineinpassen.
So funktioniert das Ausführen von 70B-Modellen auf Consumer-Hardware tatsächlich. Ein 4-Bit-quantisiertes 70B-Modell braucht insgesamt ~40 GB, aber ein einzelner Layer benötigt nur ~1–2 GB. Mit 24 GB VRAM und Prefetching kannst du das Modell mit moderatem Performance-Verlust betreiben – vielleicht 30–50 % langsamer, als wenn es komplett in den VRAM passen würde.
NVMe als erweiterter Speicher
Der aggressivste Ansatz nutzt NVMe-SSDs als dritte Stufe des GPU-Speichers. Die Bandbreite ist im Vergleich zum VRAM miserabel (~7 GB/s gegenüber ~1.000 GB/s), dafür ist die Kapazität praktisch unbegrenzt. Eine 4-TB-NVMe-SSD kostet 200 $ und kann dutzende große Modelle gleichzeitig speichern.
Projekte wie NVIDIAs Greenboost setzen das transparent um – das GPU-Speichersystem wird auf NVMe erweitert, mit intelligentem Prefetching, um die Auswirkungen der Bandbreitenbeschränkung zu minimieren. Bei Inferenz-Workloads, in denen die GPU einen großen Teil der Zeit rechnet (und nicht nur Daten verschiebt), lässt sich die NVMe-Latenz durch die Überlappung mit der Berechnung vollständig verstecken.
Die Performance hängt stark vom Workload ab. Compute-bound-Operationen (große Matrixmultiplikationen) verstecken Transferlatenz gut. Memory-bound-Operationen (Attention-Mechanismen mit großem Kontext) hingegen nicht. In der Praxis funktioniert NVMe-Offloading am besten bei Batch-Inferenz großer Modelle mit kleinen Batch-Größen – genau der Anwendungsfall für lokale LLM-Inferenz.
Apples Vorteil beim Unified Memory
Apples Unified-Memory-Architektur von Apple Silicon verfolgt einen völlig anderen Ansatz: Sie hebt die Unterscheidung zwischen VRAM und RAM komplett auf. CPU und GPU teilen sich denselben physischen Speicherpool. Es gibt kein ‚Offloading‘, weil es keine Trennung gibt – die GPU greift auf denselben Speicher zu wie die CPU.
Das löst das Bandbreitenproblem nicht – die Speicherbandbreite der M-Serie (~400 GB/s beim M4 Max) liegt unter der einer dedizierten GPU –, aber es beseitigt den PCIe-Engpass, der Offloading auf diskrete GPUs so langsam macht. Ein Mac mit 128 GB Unified Memory kann ein 70B-Modell komplett im GPU-zugänglichen Speicher unterbringen, ganz ohne Offloading-Overhead.
Der Kompromiss: Für Workloads, die vollständig in den VRAM einer dedizierten GPU passen, ist der Spitzendurchsatz niedriger. Für Workloads, die nicht hineinpassen, ist die Performance aber deutlich besser. Bei der Inferenz großer Modelle, die den VRAM einer diskreten GPU übersteigen, ist Apple Silicon trotz geringerer Rohrechenleistung oft schneller als eine diskrete GPU mit Offloading.
Was das für Entwickler bedeutet
Wenn du Anwendungen baust, die GPUs nutzen – ML-Inferenz, Grafik, wissenschaftliches Rechnen –, beeinflusst die VRAM-Beschränkung deine Architekturentscheidungen ganz konkret.
- Kenne die Größe deines Working Sets. Profiliere deine GPU-Speichernutzung. Nicht die maximale Allokation, sondern das Working Set zu jedem Zeitpunkt. Liegt dein Peak bei 48 GB, aber keine einzelne Operation braucht mehr als 8 GB aktive Daten, funktioniert Offloading gut. Braucht eine einzelne Operation tatsächlich 48 GB gleichzeitig, brauchst du eine größere GPU.
- Wähle deine Offloading-Strategie anhand des Zugriffsmusters. Sequentieller Zugriff (Layer-für-Layer-Inferenz) funktioniert hervorragend mit Prefetching. Zufälliger Zugriff (Attention über große Kontexte) nicht. Finde heraus, welchem Muster dein Workload folgt.
- Quantisierung ist meist günstiger als Offloading. Wenn du dein Modell von FP16 auf INT4 reduzierst, sinkt der Speicherbedarf um den Faktor 4 bei nur moderatem Qualitätsverlust. Offloading ins System-RAM bringt zusätzliche Latenz ohne Qualitätsverlust, spart aber nur begrenzt Speicher. Erst quantisieren, dann auslagern.
- Die Batch-Größe ist dein wichtigster Stellhebel. Größere Batches brauchen mehr Speicher, verteilen den Overhead aber besser. Kleinere Batches brauchen weniger Speicher, verarbeiten aber weniger Elemente pro Sekunde. Wenn du nahe am VRAM-Limit bist, ist eine kleinere Batch-Größe die einfachste Lösung.
- Behalte die Speicherfragmentierung im Blick. Die CUDA-Speicherallokation kann den VRAM mit der Zeit fragmentieren, besonders bei Eingaben variabler Länge. Du kannst insgesamt 8 GB frei haben, aber keinen einzigen zusammenhängenden 2-GB-Block.
torch.cuda.memory_stats()von PyTorch zeigt die Fragmentierung an.torch.cuda.empty_cache()kann helfen, ist aber kein Allheilmittel.
GPU-Speicher wird für große Compute-Workloads immer der Engpass bleiben. Modelle wachsen schneller als der VRAM. Doch die Werkzeuge, um diesen Engpass zu managen – Unified Memory, intelligentes Offloading, mehrstufiges Caching –, werden so gut, dass ‚passt nicht in den VRAM‘ keine harte Grenze mehr ist. Es ist ein Performance-Kompromiss, und zunehmend ein beherrschbarer.


