deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

KV cache boyutlandırması: Yerel bir LLM'in VRAM'e sığıp sığmayacağına karar veren aritmetik

Bir dev.to rehberi, KV cache boyutlandırmasını tahmine dayalı bir işlemden aritmetik bir hesaba dönüştürüyor: token başına bir formül, quantization tabloları ve tahsisatı kontrol eden llama.cpp ile Ollama bayraklarıyla.

KV cache boyutlandırması: Yerel bir LLM'in VRAM'e sığıp sığmayacağına karar veren aritmetik

İlk token üretilmeden önce yapılan tahsisat

Tüketici GPU'larında yerel model çalıştıran geliştiriciler sıkça tanıdık bir duvara çarpar: ağırlıklar VRAM'e sığar ama model yüklenmeyi reddeder ya da kart neredeyse belleği tükendiği için üretim saniyeler sürer. dev.to'da yayımlanan bir rehbere göre suçlu neredeyse hiçbir zaman model dosyası değildir. Suçlu, her attention katmanının geçmişi yeniden hesaplamak zorunda kalmaması için tuttuğu, token başına anahtar (key) ve değer (value) tensörleri olan KV cache'tir — önceden ayrılan, bağlam uzunluğuyla doğrusal biçimde büyüyen ve 32K token'da 7B bir modelde gigabaytlarla ölçülen bir bellek.

Tek bir formül ve GQA'nın neden baskın olduğu

Standart bir full-attention transformer için gönderi, token başına maliyeti şöyle veriyor:

2 * n_layers * n_kv_heads * head_dim * bytes_per_element

İki çarpanı K ve V tensörlerini kapsar. Yazarın vurguladığı gibi, insanları şaşırtan terim veri tipi değil, KV head sayısıdır. Qwen2.5-7B-Instruct, 128'lik head boyutuyla 28 katmana ve 4 KV head'e sahiptir; bu da token başına 28.672 önbellek değerine karşılık gelir — f16'da 56 KiB, yani üretim daha başlamadan 32.768 token'lık bir bağlamda 1,75 GiB. Mistral-7B-Instruct-v0.3 aynı head boyutunu paylaşır ama 32 katmanı ve 8 KV head'i vardır: token başına 128 KiB ve 32K'da 4 GiB. Aynı parametre sayıları, iki kattan fazla cache.

Bu, küçük ölçekte grouped-query attention'ın ta kendisidir. Düz multi-head attention kullanan (32 KV head) bir 7B model, token başına 512 KiB, yani 32K'da 16 GiB belleğe ihtiyaç duyar; gönderi bunu, kimsenin tüketici GPU'ları için 7B MHA model çıkarmamasının nedeni olarak gösteriyor. Modelleri karşılaştırırken önce KV head sayısına ve katman sayısına bakın; toplam parametre sayısı bağlam maliyeti hakkında neredeyse hiçbir şey söylemez. Rehberden iki uyarı: bazı mimariler head boyutunu türetmek yerine config.json'da açıkça tanımlar ve sliding-window ya da hibrit attention modelleri tam geçmişi tutmaz, dolayısıyla formül onlar için bir üst sınırdır.

Quantize edilmiş cache'ler tam olarak yarım değil

llama.cpp, quantize edilmiş bir cache'te her değer için bir float saklamaz. 32 değerlik bloklar ve bir ölçek (scale) saklar: q8_0 blok başına 34 byte, q4_0 ise 18 byte yer tutar. Bu ek yük yüzünden "quantization belleği yarıya indirir" şeklindeki yaygın tavsiye doğruya yakın ama yanlıştır — q8_0 cache'in yüzde 47'sini, yüzde 50'sini değil; q4_0 ise yüzde 72'sini, yüzde 75'ini tasarruf eder. 4 GiB'lik bir cache'te iddia ile gerçek arasındaki fark yaklaşık 120 MiB'dir ve 8 GB'lık bir kartta 14B model çalıştırırken bu fark önem taşır. 32K'da Qwen örneği 1,75 GiB'den (f16) 952 MiB'e (q8_0) ya da 504 MiB'e (q4_0) düşer; Mistral 4 GiB'den 2,13 GiB'e ya da 1,13 GiB'e iner. Bu rakamlar saf cache'tir — ağırlıklar, compute buffer ve CUDA context bunların üzerinde yer alır.

Tahsisatı gerçekten kontrol eden bayraklar

llama.cpp'de -c bağlam havuzunu (context pool) belirler ve ayarlanmazsa modelin eğitim bağlamı devralınır — 128K token için eğitilmiş bir modelde bu, out-of-memory çöküşüne giden kolay bir yoldur. -ctk ve -ctv bayrakları K ve V cache tiplerini bağımsız olarak ayarlar ve -fa on Flash Attention'ı zorunlu kılar: onsuz V cache'ini quantize etmek bağlam oluşturulurken açık bir hatayla başarısız olur — llama.cpp issue #10378'de izlenen bir davranış. Cache yükleme anında ayrıldığı için gönderi, trafik gönderdikten sonra değil, önce nvidia-smi ile VRAM'i ölçmeyi öneriyor.

Daha sessiz üç ayar da bütçeyi etkiler. --fit varsayılan olarak açıktır ve belleğe sığması için bağlamı sessizce küçültür; varsayılan alt sınır 4.096 token'dır, yani 128K'lık bir istek sessizce 4K'a dönüşebilir. --cache-ram, adına rağmen host RAM'dir — varsayılan 8.192 MiB — ve boşta duran slotların prompt cache'lerini park etmek için kullanılır. --no-kv-offload KV cache'i sistem belleğinde tutar ve boşalan VRAM karşılığında gecikme (latency) ödünler.

Ollama aynı fizik mirasını ekstra bir tuzakla devralır: varsayılan bağlamı, model ne için eğitilmiş olursa olsun 4.096 token'dır; bir modelin uzun bir belgenin ilerleyen bölümlerini "unutmuş" gibi görünmesinin nedeni budur. OLLAMA_CONTEXT_LENGTH ortam değişkeni bu değeri yükseltir.

Neden önemli

Bağlam penceresi, geliştiricilerin en çok tahminle belirlediği bütçe kalemidir ve tahmin, tam da yüklenme anındaki OOM'lere ve uzun belgeleri unuttuğu izlenimi veren modellere yol açar. Rehber bu tahmini kısa bir hesaba dönüştürür: config.json'u okuyun, formülü uygulayın, bir cache tipi seçin ve trafiğe açmadan önce tahsisatı doğrulayın. Ayrıca 8–16 GB kartlarda model seçimini yeniden çerçeveler: aynı parametre sayısına sahip iki 7B model, bağlam maliyetinde 2 kattan fazla fark yaratabilir — bu da çoğu zaman kullanılabilir bir 32K pencere ile hiç pencere olmaması arasındaki farktır.

  • #local-llms
  • #llama-cpp
  • #ollama
  • #kv-cache
  • #quantization