Discovery
Попробуйте другие наши приложения
Сколько VRAM нужно для LLM: как посчитать веса, KV cache и overhead
29 мая 2026 г.

Больше интересного про инференс, AI-инфраструктуру и практику с LLM я публикую в Telegram-канале @fuckup_files.

Один из первых вопросов, который возникает у каждого, кто хочет запустить локальную LLM: сколько VRAM нужно для модели и влезет ли она в мою видеокарту? Ответ «посмотри на размер файла модели» — неправильный. Память под веса (weights) — это только часть истории, а на длинном контексте всё начинает съедать KV cache, про который новички обычно забывают.

В этой статье разберём по косточкам, из чего складывается потребление видеопамяти (VRAM) при инференсе LLM, дам формулы, по которым можно посчитать всё руками, и покажу на конкретных примерах (Llama 3.1 8B и 70B), почему «модель на 16 ГБ» может не запуститься на карте с 24 ГБ.

TL;DR

Потребление VRAM при инференсе складывается из трёх частей:

VRAM_total ≈ Веса + KV cache + Overhead
  • Веса (weights): число_параметров × байт_на_параметр. FP16 → 2 байта, FP8/INT8 → 1 байт, INT4 → ~0.5 байта.
  • KV cache: растёт линейно с длиной контекста и числом параллельных запросов. Вот где «прячется» память на длинном контексте.
  • Overhead: активации (activations), CUDA-контекст, фрагментация, буферы фреймворка — обычно ещё 1–3+ ГБ.
МодельFP16 веса+ KV cache (контекст 8k, 1 запрос)Реалистичный минимум VRAM
Llama 3.1 8B~16 ГБ+1 ГБ~18–19 ГБ
Llama 3.1 70B~140 ГБ+2.5 ГБне влезает в одну карту

Если очень коротко: под веса прикидывайте «число параметров × байт на параметр», а сверху закладывайте запас под KV cache и overhead. Не влезает — квантуйте, режьте контекст или раскидывайте модель на несколько GPU.

Из чего складывается VRAM при инференсе

Когда модель работает на инференсе, в видеопамяти одновременно живут четыре вещи:

  1. Веса модели (model weights). Загружаются один раз и лежат в памяти постоянно. Самая предсказуемая часть.
  2. KV cache. Кэш ключей и значений (keys/values) механизма внимания. Хранит «прошлое» для каждого токена в контексте, чтобы не пересчитывать его на каждом шаге генерации. Подробно про сам механизм — в отдельной статье KV-cache в моделях transformers.
  3. Активации (activations). Промежуточные тензоры прямого прохода. Зависят от batch size и длины, но обычно меньше первых двух.
  4. Overhead фреймворка. CUDA-контекст (сотни МБ только на инициализацию), буферы communication-библиотек, фрагментация аллокатора, рабочие буферы. Это «налог», который легко недооценить.

Первые две части — главные. Дальше разберём каждую по формуле.

Память под веса: считаем по параметрам

Память под веса считается тривиально:

VRAM_weights ≈ N_params × bytes_per_param

bytes_per_param зависит от точности (precision), в которой загружена модель:

ТочностьБайт на параметрПример: 8BПример: 70B
FP324~32 ГБ~280 ГБ
FP16 / BF162~16 ГБ~140 ГБ
FP8 / INT81~8 ГБ~70 ГБ
INT4 (AWQ/GPTQ/GGUF Q4)~0.5~4–5 ГБ~35–40 ГБ

Отсюда удобное эмпирическое правило: в FP16 модель занимает примерно вдвое больше гигабайт, чем у неё миллиардов параметров. 7–8B → ~16 ГБ, 70B → ~140 ГБ.

INT4 на практике даёт не ровно 0.5 байта на параметр: к квантованным весам добавляются scale-факторы и zero-points, плюс часть слоёв (например, эмбеддинги или нормализации) нередко остаётся в более высокой точности. Поэтому закладывайте реальные ~4.5–5 ГБ на 8B и ~38–42 ГБ на 70B. Что и как квантовать под своё железо — разбирал в статье Квантизация LLM в 2026: FP16, FP8, INT8, INT4, AWQ, GPTQ и GGUF.

KV cache: вот где прячется контекст

Если веса — это фиксированная стоимость, то KV cache — переменная, и именно она ломает наивные прикидки «модель 16 ГБ → карта 24 ГБ → всё ок».

Размер KV cache на один токен считается так:

bytes_per_token = 2 × num_layers × num_kv_heads × head_dim × bytes_per_element

Разберём множители:

  • 2 — отдельно храним K (ключи) и V (значения).
  • num_layers — число слоёв трансформера.
  • num_kv_heads — число KV-голов. Это самый частый источник ошибки. В современных моделях используется grouped-query attention (GQA), где KV-голов меньше, чем attention-голов. Брать нужно именно num_kv_heads, а не общее число голов внимания.
  • head_dim — размерность одной головы (обычно hidden_size / num_attention_heads).
  • bytes_per_element — точность кэша: 2 байта для FP16/BF16, 1 байт для FP8/INT8-кэша.

Полный размер KV cache:

VRAM_kv = bytes_per_token × context_length × concurrent_sequences

То есть он растёт линейно и по длине контекста, и по числу параллельных запросов. Удвоили контекст — удвоили KV cache. Посадили 10 пользователей одновременно — умножили на 10.

Почему GQA так важен

Возьмём Llama 3.1 70B: 80 слоёв, 64 attention-головы, но всего 8 KV-голов (GQA), head_dim 128. Если по ошибке посчитать по 64 головам, получите KV cache в 8 раз больше реального — и сделаете вывод, что нужны 4 GPU вместо одной-двух.

Вот реальные числа на токен (FP16) для двух популярных моделей:

МодельLayersKV headshead_dimKV cache на токен (FP16)
Llama 3.1 8B328128~128 КиБ (0.125 МБ)
Llama 3.1 70B808128~320 КиБ (0.3125 МБ)

Как контекст съедает VRAM

Умножаем «на токен» на длину контекста (один запрос, FP16-кэш):

Длина контекстаKV cache, 8BKV cache, 70B
4k~0.5 ГБ~1.25 ГБ
8k~1 ГБ~2.5 ГБ
32k~4 ГБ~10 ГБ
128k~16 ГБ~40 ГБ

Обратите внимание: у Llama 3.1 8B при контексте 128k KV cache (16 ГБ) сопоставим с самими весами (16 ГБ). А если поднять batch (несколько одновременных запросов), KV cache легко станет главным потребителем VRAM. Это не баг — это и есть причина, по которой длинный контекст «дорогой».

Активации, фрагментация и overhead фреймворка

Третья часть — то, что не сводится к красивой формуле, но что регулярно отъедает 1–3 ГБ и больше:

  • CUDA-контекст. Сотни МБ просто на инициализацию рантайма на каждой карте.
  • Активации (activations). Промежуточные тензоры. На инференсе они небольшие по сравнению с обучением, но при больших batch и длинном prefill заметны.
  • Фрагментация аллокатора. Память выделяется блоками; часть теряется на «дыры». Именно с этим борется PagedAttention в vLLM, аллоцируя KV cache страницами.
  • Рабочие буферы. CUDA graphs, временные тензоры, communication-буферы при multi-GPU.

На практике это значит: даже если по формуле получилось «впритык», в реальности нужен запас. Считайте теоретический минимум, прибавляйте overhead и не планируйте загрузку выше ~90% VRAM.

Как это видит vLLM

Здесь важная деталь, на которой спотыкаются многие. vLLM не «берёт сколько надо» — он заранее резервирует фиксированную долю всей видеопамяти под себя, параметром gpu_memory_utilization (по умолчанию 0.9, в свежих стабильных версиях — 0.92). Логика такая:

KV_cache_pool ≈ gpu_memory_utilization × total_VRAM − weights − activations

Сначала загружаются веса, а весь остаток из зарезервированной доли уходит в пул KV cache. Отсюда два практических следствия:

  1. Если gpu_memory_utilization × total_VRAM меньше размера весов — vLLM просто не стартует (KV-пул отрицательный). Классический OOM ещё до первого запроса.
  2. Чем больше весят веса, тем меньше остаётся под контекст и батч. Поэтому на тесной по памяти карте квантизация освобождает место не только «под модель», но и под более длинный контекст и больший batch.
# Тесно по памяти — можно осторожно поднять долю под KV cache
vllm serve meta-llama/Llama-3.1-8B-Instruct \
  --gpu-memory-utilization 0.92 \
  --max-model-len 8192

Собираем всё вместе: формула и примеры

Итоговая прикидка:

VRAM_total ≈ N_params × bytes_per_param                       # веса
           + 2 × layers × kv_heads × head_dim × bytes         # KV на токен
             × context_length × concurrent_seqs               # × контекст × запросы
           + overhead (≈ 1–3+ ГБ)

Пример 1: Llama 3.1 8B на одной RTX 3090 (24 ГБ)

FP16, контекст 8k, один запрос:

  • Веса: ~16 ГБ
  • KV cache (8k × 0.125 МБ): ~1 ГБ
  • Overhead: ~1.5–2 ГБ
  • Итого: ~18.5–19 ГБ → влезает в 24 ГБ, остаётся запас под небольшой batch.

Поднимаем контекст до 32k: KV cache становится ~4 ГБ, итого ~22 ГБ — впритык, на батч места почти нет. Решение — INT4: веса падают до ~5 ГБ, и под контекст с батчем освобождается куча места.

Пример 2: Llama 3.1 70B — почему одной карты мало

FP16 веса 70B — это ~140 ГБ. Это не влезет ни в RTX 3090/4090 (24 ГБ), ни даже в H100 (80 ГБ). Варианты:

  • INT4: ~38–42 ГБ под веса. В одну 24 ГБ карту всё ещё не лезет. Две RTX 3090 (48 ГБ суммарно) — впритык по весам, на KV cache почти ничего не остаётся.
  • FP8 на H100 (80 ГБ): ~70 ГБ веса + немного KV — помещается, но плотно.
  • FP16 на 2× H100 (160 ГБ) через tensor parallel: комфортно.

Именно поэтому большие модели запускают на нескольких GPU — раскидывая веса и KV cache по картам через tensor parallel или pipeline parallel. Как это сделать на практике (несколько видеокарт, два сервера, Ray + vLLM) — в статье Распределённый запуск LLM на нескольких GPU с помощью Ray и vLLM.

Почему модель не влезает: быстрый чеклист

Поймали CUDA out of memory или vLLM не стартует — идём по списку от дешёвого к дорогому:

  1. Уменьшить max_model_len. Самый быстрый рычаг: контекст 128k → 16k часто решает проблему, потому что режет максимальный размер KV cache.
  2. Квантовать модель. FP16 → FP8 (÷2) или INT4 (÷4) по весам. Это и про «влезет», и про «останется место под KV cache».
  3. Снизить batch / число параллельных запросов. KV cache линеен по числу одновременных последовательностей.
  4. Проверить gpu_memory_utilization. Если стоит 0.7 «на всякий случай» — поднимите до 0.9–0.92, чтобы отдать остаток под KV cache. Но помните: на этой же карте должно хватить и системе.
  5. Включить FP8-кэш для KV. Кэш в 1 байт вместо 2 — это ×2 к ёмкости по контексту.
  6. Раскидать на несколько GPU. Tensor parallel делит и веса, и KV cache между картами. Когда модель физически не влезает в одну карту — это единственный путь.

Сколько VRAM нужно под популярные конфигурации (2026)

Грубый ориентир, FP16/типовая квантизация, умеренный контекст и batch:

Хочу запуститьМинимум VRAMРеалистичный сетап
7–8B, FP16, контекст до 8k~20 ГБ1× RTX 3090/4090 (24 ГБ)
7–8B, INT4, длинный контекст~10–12 ГБ1× карта 12–16 ГБ
32–34B, INT4~24–28 ГБ1× 24 ГБ впритык / 2× 24 ГБ
70B, INT4~44–48 ГБ2× RTX 3090 / 1× A100 80 ГБ
70B, FP8/FP16~80–160 ГБ1–2× H100/A100 80 ГБ

Прежде чем мерить производительность, убедитесь, что выбрали адекватный контекст и batch под свою VRAM — про то, как корректно снимать TTFT, TPOT и эффективную ёмкость KV cache, писал в Как бенчмаркать локальную LLM в 2026.

Частые вопросы

Сколько VRAM нужно для 7B/8B модели? В FP16 — около 16 ГБ под веса плюс 1–4 ГБ под KV cache в зависимости от контекста, то есть реалистично 18–22 ГБ. В INT4 уложитесь в 10–12 ГБ.

Почему модель «на 16 ГБ» не влезает в карту с 24 ГБ? Потому что 16 ГБ — это только веса. Сверху идут KV cache (растёт с контекстом и батчем) и overhead фреймворка. На длинном контексте или с несколькими параллельными запросами суммарно легко выходит за 24 ГБ.

Как уменьшить размер KV cache? Короче контекст (max_model_len), меньше параллельных запросов, FP8-кэш вместо FP16, плюс GQA/prefix caching снижают эффективное потребление. Подробнее про устройство кэша — в KV-cache в моделях transformers.

Можно ли запустить 70B на двух RTX 3090? Да, но только в квантизации (INT4 ~40 ГБ помещается в 48 ГБ суммарно) и с коротким контекстом — на KV cache остаётся мало места. Веса делятся между картами через tensor parallel; как настроить — в статье про распределённый инференс.

Что важнее для VRAM — размер модели или длина контекста? На коротком контексте доминируют веса. На длинном контексте (32k–128k) или при большом batch KV cache догоняет и перегоняет веса. Считать нужно обе части.


Заинтересовало? Больше практических разборов про LLM, инференс и AI-инфраструктуру — в моём Telegram-канале @fuckup_files.

Мой тг · про факапы@fuckup_files