Kembali ke blog

Konteks 128k di desktop itu bohong. Cache KV yang melahapnya.

22 September 2026

Semua kartu model lokal kini memamerkan jendela 128k. Di desktop, angka itu adalah kontrak sewa yang RAM Anda tanda tangani tanpa membaca. Penentu seberapa jauh Anda bisa mendorong dokumen panjang bukan bobotnya — melainkan cache KV, dan ia skala dengan konteks seperti pajak yang disepakati dalam mata uang orang lain.

Jendela konteks bukan fitur yang Anda nyalakan. Ia sewa memori yang Anda bayar setiap detik server berjalan.

Berapa RAM yang benar-benar dipakai konteks 128k?

Aritmetikanya publik dan pendek. Seperti diurai Transformer Inference Arithmetic, cache KV menyimpan dua tensor — key dan value — untuk setiap layer, setiap KV head, setiap token:

cache_bytes = 2 × layer × konteks × kv_head × head_dim × byte_per_elemen

Ambil Llama 3.1 8B: 32 layer, 8 KV head, head_dim 128, langsung dari config.json di Hugging Face. Pada 131.072 token di fp16 (2 byte):

2 × 32 × 131072 × 8 × 128 × 2 = 17.179.869.184 byte ≈ 16 GiB

Bobot model yang sama di fp16 beratnya sekitar 16 GiB. Pada konteks maksimum, cache sebesar model yang menaunginya. “Model 8B yang muat di 16 GiB” diam-diam menjadi soal 32 GiB begitu Anda naikkan num_ctx ke 128k.

Mengapa cache tumbuh mengikuti jendela?

Karena attention harus membandingkan setiap token dengan semua token sebelumnya, dan inferensinya autoregresif — tak ada yang dihitung ulang, semua diingat. Itulah seluruh trik yang membuat generasi cepat: key dan value tiap token dihitung sekali lalu disimpan. Penyimpanan per token konstan, jadi totalnya linier terhadap konteks. 128k bukan “angka yang lebih besar” — itu 128× cache jendela 1k, dialokasikan sepanjang sesi.

Grouped-query attention (GQA) adalah diskonnya di sisi model: KV head lebih sedikit, cache lebih ramping. Qwen2.5 7B memakai 28 layer dengan hanya 4 KV head (config di sini), jadi jendela 128k yang sama berbiaya sekitar 7 GiB di fp16 — lega sungguhan, dan salah satu alasan model-model itu terasa lebih bersahabat di mesin sederhana.

Model (fp16)Layer × KV headCache KV @ 128kBobotCache vs bobot
Llama 3.1 8B32 × 8~16 GiB~16 GiB~100 %
Qwen2.5 7B28 × 4~7 GiB~15 GiB~47 %

Hitung sendiri — inilah seluruh pemeriksaannya:

def kv_cache_gib(layers, kv_heads, head_dim, ctx, bytes_per=2):
    return 2 * layers * ctx * kv_heads * head_dim * bytes_per / 2**30

print(kv_cache_gib(32, 8, 128, 131_072))  # Llama 3.1 8B  -> 16.0
print(kv_cache_gib(28, 4, 128, 131_072))  # Qwen2.5 7B    -> 7.0

Yang tak disebut angka marketingnya

Inilah buku besar yang jujur dari argumen ini — termasuk titik-titik windunya:

  • Prefill adalah tagihan kedua. Sebelum token jawaban pertama, seluruh prompt diproses sekaligus. Prompt 100k token berarti menelan 100k token sebelum karakter pertama muncul. Di 3060, itu hitungan menit, bukan milidetik.
  • Model sliding-window mematahkan hitungan — demi keuntungan Anda. Arsitektur ala Mistral membatasi attention pada jendela tetap per layer, jadi cache berhenti tumbuh. Rumus sederhana melebih-lebihkan mereka. Tulisan ini berlaku untuk transformer full-attention — mayoritas yang orang jalankan.
  • Kuantisasi KV nyata tapi parsial. llama.cpp bisa menyimpan KV dalam q8_0, memangkas cache kira-kira separuh dengan risiko kualitas. Setengah dari 16 GiB tetap 8 GiB.
  • Spesifikasinya jarang menyebut KV head. Anda harus menggali config.json untuk menemukannya — itu sendiri bicara banyak tentang cara angka itu dirancang untuk dibaca.

Tak ada yang membuat konteks panjang jadi sia-sia. RAG ada justru karena mengisi penuh jendela adalah cara mahal untuk berkata “baca bagian 4”. Tapi kartu yang mencetak “128k” tanpa mencetak tagihan memorinya itu menjual mobil lewat top speed tanpa pernah menyebut tangki bensin.

Tak ada yang membaca 128.000 token. RAM Anda tetap membayarnya, semuanya.

Obatnya membosankan: atur konteks sesuai yang beban kerja Anda benar-benar pakai. Jendela 32k berbiaya seperempat cache 128k dan menutup hampir semua prompt yang benar-benar dikirim satu developer. Ini disiplin buku besar yang sama dengan aritmetika RAM untuk LLM lokal — ukuran model hanya separuh anggaran, dan level kuantisasi mengecilkan bobot tapi menyisakan hitungan cache tak tersentuh.

Kalau cache adalah harga sebenarnya dari konteks, mengapa kartu model menjual jendelanya dan tak pernah tagihannya? Dan babak pengakuan: konteks terbesar apa yang benar-benar Anda isi sampai token terakhir — dan hasilnya membenarkan gigabyte-nya? Komentar terbuka; tulisan seri berikutnya memihak sisi yang kalah.

FAQ

Berapa RAM yang dipakai jendela konteks 128k?

Untuk Llama 3.1 8B di fp16, cache KV saja beratnya sekitar 16 GiB pada 131.072 token — kira-kira sebesar bobot modelnya. Rumus: 2 × layer × konteks × KV head × head_dim × byte.

Mengapa konteks panjang memakai lebih banyak memori?

Setiap token dalam cache menyimpan tensor key dan value untuk setiap layer attention. Konteks dua kali lipat, cache dua kali lipat. Alokasinya tetap ada meski Anda tak pernah mengisi penuh jendelanya.

Bagaimana mengurangi memori cache KV di LLM lokal?

Atur konteks sesuai yang benar-benar dipakai, pilih model dengan grouped-query attention (KV head lebih sedikit), kuantisasi cache KV ke q8 bila runtime mendukung, atau pakai arsitektur sliding-window dan hibrida.

— mrsaynothing

— mrsaynothing

Opini di-load-test sebelum tayang. Kebanyakan.

Dapatkan argumen berikutnya lewat email

Satu email per tulisan. Setuju atau bongkar habis.

self-hosted · tanpa pihak ketiga · berhenti langganan sekali klik

apa ini?

git stash: satu file saja, tanpa kehilangan sisanya

Suka tulisannya? Saya membangun seperti ini untuk hidup. pekerjakan saya