Koliko VRAM-a ti stvarno treba

Najčešća greška pri prvom pokretanju modela ide ovako: čovek pogleda veličinu fajla, uporedi je sa memorijom kartice, vidi da staje — i onda mu sve pukne na trećoj poruci u razgovoru.

Razlog je jednostavan. Težine su samo jedna od tri stavke koje troše VRAM, a ona jedina koja je konstantna. Druge dve rastu tokom rada. Ovaj tekst pokazuje kako se sve tri izračunaju unapred, pa da znaš šta ti hardver nosi pre nego što potrošiš vreme na preuzimanje.

Ako ti pojmovi KV keš i kvantizacija još ne znače mnogo, pri ruci drži rečnik AI pojmova.

Tri stavke

Ukupno zauzeće = težine + KV keš + režija

  težine   — konstantne, zavise od modela i kvantizacije
  KV keš   — raste sa dužinom konteksta i brojem korisnika
  režija   — CUDA kontekst, aktivacije, sam servis (oko 1 GB)

Zapamti ovaj obrazac. Sve dalje u tekstu je razrada njegova tri člana.

1. Težine

Veličina fajla je broj parametara pomnožen brojem bajtova po parametru. Bajtovi zavise od kvantizacije.

Kvantizacija GB po milijardi parametara Napomena
FP16 / BF16 2.0 Puna preciznost, originalni format
Q8_0 1.1 Gubitak kvaliteta praktično nemerljiv
Q5_K_M 0.75 Kompromis kada Q4 nije dovoljno dobar
Q4_K_M 0.6 Podrazumevani izbor za lokalni hosting
Q3_K_M 0.48 Kvalitet primetno pada, samo iz nužde

Za Q4_K_M je pravilo palca da model klase NB zauzima otprilike 0.6 × N gigabajta. Model od 27B je oko 16 GB, model od 8B oko 5 GB. Proveri sam na bilo kom modelu koji imaš — poklopiće se u granicama nekoliko procenata.

Model FP16 Q8_0 Q4_K_M
4B 8 GB 4.4 GB 2.4 GB
8B 16 GB 8.8 GB 4.8 GB
27B 54 GB 30 GB 16 GB
70B 140 GB 77 GB 42 GB

Zamka sa MoE modelima

Kod modela označenog kao 122B-A10B u memoriju ide svih 122 milijarde, ne deset. Aktivni parametri određuju brzinu, ne zauzeće. Ovo je najskuplja greška u računici, jer razlika ume da bude dvanaestostruka.

2. KV keš

Ovo je stavka koja obara postavke koje su „radile juče". KV keš čuva međurezultat za svaki token u kontekstu i raste linearno sa dužinom razgovora.

bajtova po tokenu = 2 × slojevi × kv_glave × dimenzija_glave × bajtova_po_elementu

  2                    — jedan zapis za K, jedan za V
  slojevi              — num_hidden_layers iz config.json
  kv_glave             — num_key_value_heads iz config.json
  dimenzija_glave      — hidden_size / num_attention_heads
  bajtova_po_elementu  — 2 za FP16

Sve vrednosti stoje u config.json pored težina:

$ grep -E 'num_hidden_layers|num_key_value_heads|num_attention_heads|hidden_size' config.json
  "hidden_size": 4096,
  "num_attention_heads": 32,
  "num_hidden_layers": 32,
  "num_key_value_heads": 8,

Za taj model dimenzija glave je 4096 / 32 = 128, pa je po tokenu:

2 × 32 × 8 × 128 × 2 = 131 072 bajta = 128 KB po tokenu
Kontekst KV keš (128 KB/token) KV keš (256 KB/token)
4 096 0.5 GB 1.0 GB
16 384 2.0 GB 4.0 GB
32 768 4.0 GB 8.0 GB
131 072 16 GB 32 GB

Pogledaj poslednji red. Kontekst od sto trideset hiljada tokena ume da košta više memorije nego sam model. Zato deklarisani milionski kontekst ne znači da ćeš ga na svom hardveru koristiti — znači samo da ga model podnosi.

Dve stvari koje ovo smanjuju

GQA (grupisane upitne glave) je razlog zašto num_key_value_heads ume da bude osam umesto trideset dva. Kod starijih modela bez GQA taj broj je jednak broju glava pažnje, pa je KV keš četiri puta veći. Ako gledaš stariji model i brojka ti deluje neverovatno — nije greška.

Kvantizacija KV keša ga polovi. U llama.cpp i Ollami postavlja se posebno od kvantizacije težina:

$ OLLAMA_KV_CACHE_TYPE=q8_0 ollama serve

Gubitak kvaliteta je mali, ušteda velika. Ovo je prva stvar koju uključuješ kada ti kontekst ne staje.

3. Režija

Na težine i KV keš ide još:

  • CUDA kontekst — oko 300 do 500 MB, čim proces dodirne karticu
  • Aktivacije — privremeni međurezultati tokom prolaza, nekoliko stotina megabajta
  • Fragmentacija — memorija koja se ne može iskoristiti jer nije u komadu

Za procenu računaj 1 GB. Kod vLLM-a i drugih produkcionih servisa i više, jer unapred rezervišu memoriju.

Puna računica: kartica od 24 GB

Model klase 27B, Q4_K_M, KV keš od 256 KB po tokenu.

Ukupno na kartici           24.0 GB
Rezervisano za sistem       -0.5 GB   (ako je kartica i za ekran)
Režija servisa              -1.0 GB
Težine (27B × 0.6)         -16.2 GB
                          ─────────
Slobodno za KV keš           6.3 GB

6.3 GB / 256 KB = oko 25 000 tokena konteksta

Zaključak: model radi udobno, ali kontekst je ograničen na dvadesetak hiljada tokena. Sa q8_0 kešom to postaje pedesetak hiljada. Sa modelom klase 20B umesto 27B — još više.

Puna računica: kartica od 8 GB

Ukupno na kartici            8.0 GB
Režija servisa              -1.0 GB
Težine (8B × 0.6)           -4.8 GB
                          ─────────
Slobodno za KV keš           2.2 GB

2.2 GB / 128 KB = oko 17 000 tokena konteksta

Sasvim upotrebljivo za analizu logova i pomoć u terminalu. Za rad sa dužim dokumentima nije.

Više korisnika istovremeno

Svaki paralelan razgovor ima svoj KV keš. Ako planiraš da servis koristi tim, računicu množi brojem istovremenih sesija — ne brojem ljudi, nego brojem onih koji stvarno kucaju u istom trenutku.

Slobodno za KV keš:              6.3 GB
Kontekst po korisniku:          8 192 tokena → 2.0 GB
Istovremenih sesija:             3

Ollama ovakav raspored ne vodi računa naročito pametno; vLLM ume da deli zajednički deo konteksta među zahtevima i tu je osetno efikasniji, o čemu govori tekst o vLLM-u.

Provera u praksi

Koliko je slobodno pre pokretanja:

$ nvidia-smi --query-gpu=name,memory.total,memory.used,memory.free --format=csv
name, memory.total [MiB], memory.used [MiB], memory.free [MiB]
NVIDIA GeForce RTX 3090, 24576 MiB, 412 MiB, 24164 MiB

Da li je model stvarno ceo na kartici:

$ ollama ps
NAME           ID          SIZE     PROCESSOR       UNTIL
qwen3:27b      a1b2c3d4    18 GB    100% GPU        4 minutes from now

Kolona PROCESSOR je ovde najvažnija. Ako piše nešto poput 65% GPU / 35% CPU, deo slojeva radi na procesoru i brzina pada višestruko. Detaljno o čitanju ovih alata ima u tekstu o nvidia-smi i nvtop.

Šta kada ne staje

Po redosledu, od najmanje do najviše bolnog:

  1. Smanji kontekst. Najjeftinije rešenje, jer većina razgovora ne koristi ni polovinu zadatog prozora.
  2. Kvantizuj KV keš na q8_0. Polovi keš uz zanemarljiv gubitak.
  3. Spusti kvantizaciju težina. Sa Q5 na Q4 ide bez razmišljanja, ispod Q4 sa oprezom.
  4. Uzmi manji model. Model klase 20B na kartici često je bolji izbor od modela klase 27B koji jedva staje.
  5. Offloading na sistemsku memoriju. Radi, ali svaki sloj koji sklizne na procesor košta brzinu.

Pravilo koje vredi zapamtiti: manji model koji ceo stane na karticu skoro uvek je bolji od većeg koji se delimično izliva u sistemsku memoriju. Razlika u brzini je red veličine, razlika u kvalitetu odgovora je nekoliko procenata.

Praktični scenariji

Scenario 1: model puca posle nekoliko poruka

CUDA error: out of memory

Klasičan rast KV keša. Model je stao na prazan kontekst, ali ne staje na pun. Smanji prozor ili kvantizuj keš.

Scenario 2: prvi odgovor brz, kasniji spori

Verovatno je deo keša prešao u sistemsku memoriju. Proveri ollama ps i skrati kontekst.

Scenario 3: model od 122B ne staje, a računao si na deset milijardi

Pročitao si aktivne parametre umesto ukupnih. U memoriju ide ceo model.

Scenario 4: kupovina kartice za tim od pet ljudi

Ne gledaj samo model — pomnoži KV keš brojem istovremenih sesija. Za pet ljudi i pristojan kontekst 24 GB je tesno; četrdeset osam je udobno.

Scenario 5: model deklariše milion tokena konteksta

Deklaracija je stvar modela, iskoristivost je stvar tvoje memorije. Izračunaj po formuli koliko ti stvarno staje i toliko i zadaj.

Kratka referenca

  • Ukupno = težine + KV keš + režija
  • Težine Q4_K_M — otprilike 0.6 GB po milijardi parametara
  • Težine FP16 — 2 GB po milijardi parametara
  • KV po tokenu = 2 × slojevi × kv_glave × dimenzija_glave × 2
  • config.json — izvor svih vrednosti za formulu
  • Režija — računaj 1 GB
  • MoE — memorija po ukupnom broju parametara, ne po aktivnom
  • GQA — smanjuje KV keš višestruko
  • OLLAMA_KV_CACHE_TYPE=q8_0 — polovi KV keš
  • ollama ps — pokazuje koliko modela je stvarno na kartici
  • nvidia-smi — slobodna memorija pre pokretanja
  • Pravilo — manji model u celosti je bolji od većeg sa offloadingom

Vežba

  1. Iz config.json bilo kog modela izračunaj KV keš po tokenu i po kontekstu od 32 768 tokena.
  2. Za svoju karticu izračunaj koliko konteksta ti ostaje uz model klase 8B u Q4_K_M.
  3. Uporedi model klase 27B u Q4_K_M i model klase 14B u Q8_0. Koji zauzima manje i koji bi izabrao?
  4. Pokreni model, otvori watch -n 1 nvidia-smi u drugom terminalu i prati zauzeće kroz dug razgovor. Zapiši rast.
  5. Za tim od tri istovremena korisnika i kontekst od 16 384 tokena izračunaj minimalnu karticu koja to nosi uz model klase 14B.

Sledeći tekst u serijalu: CPU inferencija naspram GPU inferencije

Povezano:

Comments

Popular posts from this blog

Početak u Linuxu — šta je i zašto se uči

Konverzija tipova podataka u Pythonu

groupadd