Saat VRAM GPU Anda Habis: Apa yang Harus Dilakukan
VRAM GPU sering jadi bottleneck untuk beban kerja AI dan grafis. Begini cara kerja unified memory, offloading VRAM, dan swapping NVMe di balik layar.

Pesan error yang paling sering muncul di machine learning bukan traceback Python atau shape mismatch. Yang paling sering adalah CUDA out of memory. Modelnya terlalu besar, batch size-nya terlalu lebar, atau intermediate activation-nya tidak muat di VRAM GPU Anda. RTX 4090 punya 24 GB. Model 70B parameter dalam half precision butuh sekitar 140 GB. Hitungannya memang tidak cocok, dan melempar uang untuk GPU yang lebih besar hanya menunda masalah. H100 dengan 80 GB pun tetap tidak bisa menampung model terbesar dalam satu kartu.
Tapi bagaimana kalau Anda bisa memperluas memori GPU secara transparan pakai RAM sistem, atau bahkan storage NVMe? Tools seperti Greenboost dari NVIDIA dan proyek serupa melakukan persis ini, memanfaatkan hierarki memori (VRAM → RAM sistem → SSD) untuk menjalankan beban kerja yang seharusnya tidak muat di perangkat Anda. Trade-off performanya nyata, tapi untuk banyak kasus justru cukup bisa dikelola. Untuk memahaminya, kita perlu paham dulu hierarki memori GPU itu sendiri.
Mengapa Memori GPU Berbeda dengan Memori CPU
Memori CPU dan GPU melayani pola akses yang sangat berbeda. Beban kerja CPU sensitif terhadap latensi: satu thread butuh sepotong data dan menunggu sampai data itu tiba. Cache CPU dirancang untuk meminimalkan latensi pada pola akses acak.
Beban kerja GPU sensitif terhadap throughput: ribuan thread masing-masing butuh datanya, dan GPU bisa berpindah antar-thread untuk menyembunyikan latensi. Memori GPU (HBM pada GPU datacenter, GDDR pada kartu konsumen) dirancang untuk bandwidth, yaitu mengirimkan data dalam jumlah besar per detik, meski satu akses individual bisa lebih lama dibanding cache hit CPU.
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.
Kesenjangan bandwidth inilah alasan kenapa membuat memori GPU 'virtual', yaitu mem-paging data ke RAM sistem seperti yang dilakukan CPU ke disk, tidak bisa dilakukan secara naif. CPU masih bisa menoleransi page fault dengan perlambatan sekitar 10x. Sementara GPU yang mengakses RAM sistem alih-alih VRAM mengalami penurunan bandwidth 20x. Untuk beban kerja yang terikat bandwidth (sebagian besar inferensi ML), artinya perlambatan 20x.
Cara Kerja Offloading VRAM yang Sebenarnya
Triknya bukan memperlakukan RAM sistem sebagai VRAM yang lambat. Triknya adalah melakukan prefetch data dari RAM sistem ke VRAM sebelum GPU membutuhkannya, sehingga latensinya tersembunyi di balik komputasi. Ini adalah inti dari setiap teknik perluasan VRAM yang praktis.
Selama inferensi neural network, komputasinya berjalan berurutan per layer. Saat GPU memproses layer 5, ia sudah tahu layer 6 adalah yang berikutnya. Sistem offloading yang cerdas bisa mulai mentransfer bobot layer 6 dari RAM sistem ke VRAM sambil layer 5 masih dihitung. Jika komputasinya lebih lama dari transfer (sering terjadi pada layer besar), transfer itu sepenuhnya tersembunyi dan GPU tidak pernah menganggur.
# 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
Pendekatan pipeline ini bekerja baik untuk inferensi karena computation graph-nya bisa diprediksi. Anda tahu persis bobot mana yang dibutuhkan berikutnya. Training lebih sulit karena backward pass membutuhkan activation dari forward pass, sehingga pola pergerakan datanya jauh lebih rumit.
Pendekatan yang Dipakai di Praktik
CUDA Unified Memory
CUDA Unified Memory dari NVIDIA menciptakan satu address space yang mencakup VRAM GPU dan RAM sistem. Runtime CUDA secara otomatis memindahkan page di antara keduanya berdasarkan pola akses. Ketika GPU mengakses page di RAM sistem, terjadi page fault dan page tersebut dipindahkan ke VRAM.
Keuntungannya: transparan bagi aplikasi. Kode CUDA Anda tidak perlu mengatur penempatan data. Kekurangannya: page fault itu mahal, dan heuristik migrasi runtime tidak selalu cocok dengan pola akses aplikasi. Untuk beban kerja yang bisa diprediksi seperti inferensi neural network, manajemen eksplisit jauh lebih unggul dibanding migrasi otomatis.
Offloading Layer demi Layer
Tools seperti Hugging Face Accelerate, DeepSpeed ZeRO-Inference, dan flag --mmap di llama.cpp menerapkan offloading layer secara eksplisit. Mereka hanya menyimpan layer yang aktif di VRAM dan men-stream sisanya dari RAM sistem atau disk. Model tidak perlu muat seluruhnya di VRAM, cukup satu atau dua layer dalam satu waktu.
Begini sebenarnya cara menjalankan model 70B di perangkat konsumen bekerja. Model 70B yang di-quantize 4-bit butuh sekitar 40 GB total, tapi satu layer hanya butuh sekitar 1-2 GB. Dengan VRAM 24 GB dan prefetching, Anda bisa menjalankan model ini dengan dampak performa yang moderat, mungkin 30-50% lebih lambat dibanding jika muat sepenuhnya di VRAM.
Menggunakan NVMe sebagai Memori Tambahan
Pendekatan paling agresif memakai SSD NVMe sebagai tier ketiga memori GPU. Bandwidth-nya jauh di bawah VRAM (~7 GB/s vs ~1.000 GB/s), tapi kapasitasnya nyaris tanpa batas. Drive NVMe 4 TB harganya sekitar $200 dan bisa menyimpan puluhan model besar sekaligus.
Proyek seperti Greenboost dari NVIDIA mengimplementasikan ini secara transparan. Sistem memori GPU diperluas ke NVMe, dengan prefetching cerdas untuk meminimalkan dampak keterbatasan bandwidth. Untuk workload inferensi di mana GPU banyak menghabiskan waktu untuk komputasi (bukan sekadar memindahkan data), latensi NVMe bisa tersembunyi sepenuhnya oleh overlap dengan komputasi.
Performanya sangat bergantung pada jenis workload. Operasi yang terikat komputasi (perkalian matriks besar) menyembunyikan latensi transfer dengan baik. Operasi yang terikat memori (mekanisme attention dengan konteks panjang) tidak. Dalam praktik, offloading NVMe paling cocok untuk batch inferensi model besar dengan batch size kecil, tepat untuk kasus pemakaian inferensi LLM lokal.
Keunggulan Unified Memory dari Apple
Arsitektur unified memory Apple Silicon mengambil pendekatan yang sama sekali berbeda: menghapus pembedaan antara VRAM dan RAM. CPU dan GPU berbagi satu pool memori fisik yang sama. Tidak ada 'offloading' karena tidak ada pemisahan. GPU mengakses memori yang sama dengan yang dipakai CPU.
Ini tidak menghilangkan masalah bandwidth. Bandwidth memori seri M (~400 GB/s untuk M4 Max) memang lebih rendah dibanding GPU dedicated, tapi menghilangkan bottleneck PCIe yang membuat offloading GPU terpisah terasa lambat. Mac dengan 128 GB unified memory bisa menampung model 70B sepenuhnya di memori yang bisa diakses GPU tanpa overhead offloading sama sekali.
Trade-off-nya: throughput puncak lebih rendah untuk workload yang muat sepenuhnya di VRAM GPU dedicated, tapi performanya jauh lebih baik untuk workload yang tidak muat. Untuk inferensi model besar yang melampaui VRAM GPU terpisah, Apple Silicon sering kali lebih cepat dibanding GPU terpisah dengan offloading, meski komputasi mentahnya lebih kecil.
Apa Artinya bagi Developer
Jika Anda membangun aplikasi yang memakai GPU (inferensi ML, grafis, komputasi saintifik), batasan VRAM akan memengaruhi keputusan arsitektur Anda secara konkret.
- Ketahui ukuran working set Anda. Profilkan penggunaan memori GPU Anda. Bukan alokasi puncak, tapi working set pada titik waktu tertentu. Jika puncak Anda 48 GB tapi tidak ada satu operasi pun yang butuh lebih dari 8 GB data aktif, offloading akan berjalan baik. Jika satu operasi memang butuh 48 GB sekaligus, Anda perlu GPU yang lebih besar.
- Pilih strategi offloading berdasarkan pola akses. Akses berurutan (inferensi layer demi layer) sangat cocok dengan prefetching. Akses acak (attention pada konteks besar) tidak. Ketahui pola mana yang diikuti workload Anda.
- Quantization biasanya lebih murah daripada offloading. Menurunkan model dari FP16 ke INT4 memangkas memori 4x dengan dampak kualitas yang moderat. Offloading ke RAM sistem menambah latensi tanpa dampak kualitas, tapi penghematan memorinya terbatas. Lakukan quantization dulu, baru offloading.
- Batch size adalah tombol tuning Anda. Batch lebih besar butuh memori lebih banyak tapi overhead-nya lebih efisien. Batch lebih kecil butuh memori lebih sedikit tapi memproses lebih sedikit item per detik. Saat mendekati batas VRAM, mengurangi batch size adalah perbaikan paling sederhana.
- Pantau fragmentasi memori. Alokasi memori CUDA bisa memecah VRAM seiring waktu, terutama dengan input berpanjang variabel. Bisa saja total VRAM bebas 8 GB tapi tidak ada satu blok kontigu 2 GB.
torch.cuda.memory_stats()dari PyTorch menampilkan fragmentasi.torch.cuda.empty_cache()bisa membantu, meski bukan solusi untuk semuanya.
Memori GPU akan selalu menjadi bottleneck untuk komputasi skala besar. Model berkembang lebih cepat daripada VRAM. Tapi tooling untuk mengelola bottleneck ini, seperti unified memory, offloading cerdas, dan caching multi-tier, makin matang sehingga 'tidak muat di VRAM' bukan lagi hambatan keras. Itu sekarang hanyalah trade-off performa, dan makin lama makin bisa dikelola.


