Проблема

«Модель не влезает» — OOM при запуске или под нагрузкой. VRAM — это бюджет: веса + KV-cache + overhead. Вот как посчитать, влезет ли конкретная модель в конкретное железо.

Алгоритм: 6 шагов

  1. Бюджет VRAM: суммарная VRAM кластера × gpu-memory-utilization (≈0.90) − overhead (~10–15%).
  2. Целевой workload: макс. контекст (8K / 32K / 128K?), целевая concurrency (1 / 4 / 16?) → KV-cache = f(контекст, concurrency, архитектура).
  3. Размер модели: weights_VRAM ≈ params × bytes/param × 1.2; weights + KV ≤ бюджет → максимальный размер, который влезает.
  4. Формат под GPU-архитектуру:
    • Ampere (RTX 3090/4090, A100): AWQ / GPTQ INT4 (W4A16); FP8 недоступен.
    • Hopper/Blackwell (H100/H200/B200): FP8 / NVFP4 — максимум throughput; AWQ — запасной.
    • CPU / edge / мало VRAM: GGUF Q4_K_M / Q5_K_M / Q8_0.
  5. Проверка: weights + KV + overhead ≤ бюджет? Если OOM — лестница снижения: контекст ↓ → concurrency ↓ → квант ниже (Q4) → KV-cache FP8/INT8 (--kv-cache-dtype fp8) → CPU offload → больше GPU (TP).
  6. Валидация качества: бенчмарк на целевых задачах (code / RAG / chat) vs FP16 baseline → фиксация модели + кванта в документацию.

Формулы

Веса:

weights_VRAM ≈ params × bytes/param × 1.2

×1.2 — embeddings, CUDA context. bytes/param по форматам:

Форматbytes/param27B70B
FP16/BF162~65 GB~168 GB
FP81~32 GB~84 GB
AWQ/GPTQ INT40.5~16 GB~42 GB
GGUF Q4_K_M~0.55~17 GB
GGUF Q8_0~1.07~34 GB

KV-cache (на 1 запрос):

bytes/token = 2 × n_layers × n_kv_heads × head_dim × bytes_per_element

Множитель 2 — храним и K, и V. GQA (мало KV-голов) сильно снижает размер. Пример: 27B dense, GQA, BF16 KV ≈ 1–4 GB на 32K контекст; при concurrency 4 — умножаем на 4. KV-cache не квантуется вместе с весами — это отдельный потребитель VRAM (можно FP8/INT8 KV: --kv-cache-dtype fp8).

Бюджет:

weights + KV × concurrency + overhead ≤ VRAM × gpu-memory-utilization

Форматы — когда что брать

  • FP16/BF16: 80 GB+ GPU, потеря 0% — эталон, валидация качества.
  • FP8 / NVFP4: Hopper/Blackwell, потеря <1% — production на H100, максимум throughput.
  • AWQ INT4 (W4A16): любая NVIDIA вкл. Ampere, потеря ~1–3% — default для RTX 3090/4090, лучшее качество среди 4-bit (защита «важных» весов до квантизации).
  • GPTQ INT4 (W4A16): любая NVIDIA, потеря ~2–5% (чуть хуже AWQ на code) — запасной, если AWQ-чека нет.
  • GGUF Q4_K_M / Q5_K_M / Q8_0: CPU, любая GPU, Mac; Q4 ~3–5% потери, Q8 <1% — edge, Ollama, мало VRAM, CPU offload.

Правила: Ampere → AWQ (FP8 нет); H100+ → FP8 (AWQ — fallback). Качество критично → AWQ > GPTQ; VRAM критична → GGUF Q4_K_M (лучший баланс размер/качество). Длинный контекст → KV FP8/INT8 или снизить max-model-len. MoE (35B-A3B, DeepSeek): активные параметры малы — 35B-A3B в Q4 живёт на 24 GB, 120+ tok/s.

Наш стек: Qwen3.8-27B на 2×RTX 3090

2×RTX 3090 = 48 GB, бюджет ≈ 43 GB:

ВариантРасчётВердикт
FP16~65 GBOOM, не влезает
FP8~32 GBНедоступно: на Ampere нет FP8
AWQ W4A1616 GB весов (TP=2) + KV 2–4 GB (32K, 1 req) + overhead ≈ 5 GB → ~20–25 GB✅ Наш выбор
GGUF Q4_K_M~17 GB → ~22 GBАльтернатива (llama.cpp)

Продакшн-реальность: 256K контекст → KV-cache растёт до ~18 GB, итого ~39 GB — влезает, но max-num-seqs = 2 (KV съедает бюджет — см. часть 3).

Вывод

VRAM-бюджет считается до выбора модели, а не после первого OOM. weights + KV + overhead ≤ бюджет — если запаса нет, снижаем контекст или concurrency, а не задачу.

Смежные материалы: AWQ, FP8, Тюнинг vLLM (часть 3), Подбор модели (часть 2).

← Право и ИИ: локализация данных и регуляторика 2000–2026 Особенности LLM-трафика: почему round-robin не работает →