- BrainTools - https://www.braintools.ru -
Я прогнал топ выдачи Google по «llm vram calculator» — от самого навороченного до однокнопочных. Все ошибаются в одном и том же: ни один не моделирует, что движок резервирует почти всю память [1] под пул заранее, а не раздаёт её под KV по мере запросов. Ответ «сколько запросов влезет» из-за этого всегда мимо.
Наивное большинство спотыкается ещё и о геометрию KV: на DeepSeek-V2-Lite обычная формула завышает память почти на порядок (в 7–11 раз). Разбираю обе ловушки и сверяю числа с живым vLLM.
Пишете две строки:
from vllm import LLM
llm = LLM("meta-llama/Meta-Llama-3-8B-Instruct")
Кажется, что движок положит веса, а остаток раздаст под KV по мере запросов. Так не делает ни один современный движок. vLLM при старте резервирует большой кусок VRAM под пул и пейджит KV внутрь него — флаг gpu_memory_utilization, дефолт 0.92. У SGLang то же зовётся mem_fraction_static (по умолчанию авто, около 0.9), у TensorRT-LLM — kv_cache_free_gpu_mem_fraction. Веса грузятся внутрь этого куска, KV живёт в остатке после весов и overhead; свободные ~8% VRAM под KV не пойдут никогда.
Ёмкость KV-пула поэтому считается так:
KV-пул = util · VRAM − веса − overhead
Если вы гоняете vLLM в проде, эту долю вы и так держите в голове: gpu_memory_utilization вы задаёте сами, а зачем пул выделяется одним куском, объясняет PagedAttention (arXiv:2309.06180 [2]).
Проверить, что пул посчитан верно, можно не арендуя GPU. vLLM при старте печатает строку # GPU blocks: N. Это и есть размер KV-пула. ridgepoint предсказывает то же число заранее:
llama-3-8b, 1× A100, ctx 8192: наивная формула без util обещает ~60 запросов; с поправкой на util — 54, замер vLLM — 55. Тот самый множитель, что вы и так держите в голове. С первой ошибкой [3] всё.
KV на токен зависит от архитектуры внимания [4], и на этом спотыкается большинство калькуляторов (лучшие — вроде apxml — MLA всё же распознают). У обычной GQA-модели байты на токен считаются как 2·n_kv·head_dim·L·p. У DeepSeek с MLA внимание сжато в латент, и формула другая: (d_c + d_rope)·L·p, где d_c — размерность сжатого латента, d_rope — rope-часть.
Посчитаем DeepSeek-V2-Lite руками, из его config.json:
MLA (правильно): (512 + 64)·27·2 = 31 104 Б/токен
наивная формула: 2·n_kv(16)·head_dim·27·2
head_dim=128 (hidden/heads): → 221 184 Б/токен = завышение 7.1×
head_dim=192 (qk_nope+rope): → 331 776 Б/токен = завышение 10.7×
Калькулятор, который трактует MLA как обычное внимание, подставляет 2·n_kv·head_dim. Смотря какой head_dim он возьмёт, KV завышается в 7–11 раз. Точный множитель зависит от его допущения, но порядок один, и он задокументирован в самой DeepSeek-V2 (arXiv:2405.04434 [5]): MLA сжимает KV в разы. И промах тут в обратную сторону от первой ошибки: вы решите, что модель требует почти на порядок больше карт, зря откажетесь её ставить или арендуете стойку вместо одной GPU.
С MoE та же ловушка: у DeepSeek-V2-Lite веса 16B (total), а активны 2B. Память платите за 16, скорость считаете по 2, перепутать легко.
Опираюсь я тут на измеренное: настоящие 31 104 Б/токен сняты с живого vLLM (40.79 ГиБ / 1 408 144 токенов), а (512+64)·27·2 сверьте сами. Инструмент берёт любой org/model с HuggingFace, читает конфиг и применяет формулу под конкретную архитектуру (GQA, MLA, MoE определяются сами):
Ради этого случая инструмент и писался.
Наивная прикидка, ridgepoint и живой vLLM (замер на RunPod, vLLM 0.28, util 0.90):
|
1× A100-80GB, ctx 8192 |
наивно |
ridgepoint |
замер vLLM |
|---|---|---|---|
|
llama-3-8b (GQA) |
~60 |
54 |
55 |
|
DeepSeek-V2-Lite (MLA·MoE) |
GQA-формула → 16–24 |
171 |
172 |
|
llama-3-70b AWQ |
~15 |
12 |
13 |
Оговорю рамки. Память я сверял с логами vLLM и nvidia-smi на четырёх моделях трёх архитектур (GQA, MLA, MoE) на A100, плюс перенос на H100: по байтам расхождение 1–4% и всегда чуть ниже замера, то есть недооцениваю. Счётчики запросов в таблице округлены до целого, поэтому там разрыв может выглядеть крупнее (12 против 13 — это те же байты). Это n=4, не закон природы; полный predict-vs-measured лежит в репозитории (calibration/CALIBRATION.md [6]). Побайтовый KV точен арифметически, если верно определена архитектура — ровно это определение и делает инструмент. Интервал overhead (1.5·1.8·2.2 в выводе — активации плюс CUDA-графы) уже эмпирика, её я и калибровал, отсюда полоса low/best/high. Дефолт vLLM с тех пор уехал с 0.90 на 0.92, значит реальный пул чуть больше моих чисел — я и здесь недооцениваю.
Скорость. TTFT и утилизацию компьюта (MFU, model FLOPs utilization) замерить чисто не вышло: удалённый бенчмарк мешает префилл с сетью, поэтому в выводе они помечены ~MFU literature — цифры из литературы, сам я их не мерил. Пропускную способность памяти при декоде (MBU, memory-bandwidth utilization ≈ 0.62) померил, этой цифре верю. Throughput под смешанной нагрузкой (--max-num-seqs, разные длины) v0 не считает, это следующая версия. И числа пока калиброваны на vLLM: SGLang с TensorRT-LLM пейджат KV в такой же пул, но коэффициенты под них я ещё не мерил.
Взял то, что видит обычный человек в выдаче — и pre-grab движка не моделирует никто, даже лучший из них.
apxml реально силён: распознаёт MLA, считает framework overhead, умеет KV-квант. Но Concurrent Users — это ползунок на вход, а память он складывает как «веса + активации + KV + overhead < VRAM». Что vLLM заберёт gpu_memory_utilization заранее и сколько запросов влезет в оставшийся пул — не моделирует.
smcleod и NyxKrage проще: Model + KV = Total, без overhead и без MLA (значит, на DeepSeek — те самые 7–11×). Проверьте сами за минуту по ссылкам.
И это не про «старьё»: механизм публичен с PagedAttention [2] (2023), а тулы 2026 года его всё равно не берут.
pip install ridgepoint
ridgepoint fit deepseek-ai/DeepSeek-V2-Lite --gpu h100-80gb:1 --ctx 8192
Считает локально, на ноутбуке: тянет с HuggingFace только config.json и индекс safetensors (пара КБ), больше ничего никуда не уходит (python/ridgepoint/hf.py). Жечь GPU-часы не нужно.
Дальше подставляйте что нужно. Любой HF-репозиторий подтянет конфиг сам. Карта задаётся флагом --gpu a100-80gb:1 или h100-80gb:2, а ridgepoint devices найдёт локальные. Движок — --engine vllm|sglang|llamacpp; SGLang уже работает (пул тот же pre-grab), но помечен uncalibrated — коэффициенты под него на железе я ещё не мерил. Если удобнее из кода — есть библиотечный вызов ridgepoint.fit("llama-3-70b", "a100-80gb", count=2).
Ядро на Rust считает только числа и в сеть не ходит. HF-адаптер живёт снаружи, на Python.
v0 узкий: память и ёмкость, пока два движка (vLLM и llama.cpp). Но внутри уже не наивно — веса и KV-кэш квантуются раздельно (--kv-cache-dtype fp8 вдвое увеличивает KV-ёмкость пула; кто ставит fp4-веса при fp16-кеше, обычно этого не осознаёт), а MLA/MoE/GQA определяются сами. В очереди, по одному измеренному куску за релиз:
Докалибровать движки на железе. SGLang уже запускается (--engine sglang), но пока uncalibrated — с него и начну (сам его предпочитаю), дальше TensorRT-LLM и TGI. Пул у всех один и тот же pre-grab, отличаются только коэффициенты.
Полный шкаф железа и квантов: Blackwell, H200, MI300X, NVLink. Заодно покажу, как FP8/FP4 двигают обе оси roofline — байты весов вниз и пиковые FLOPs вверх.
Скорость замером на поде, а не из литературы. Сейчас в выводе там заглушка ~MFU literature, вы её видели.
Несколько GPU: TP/PP/EP. В замерах уже вижу, что активации шардятся, а CUDA-графы на карту нет.
Спек-декодинг. Он переводит decode из memory-bound в compute-bound, тащит тебя к тому самому ridge point, в честь которого инструмент назван.
Mamba/SSM, sliding-window, гибриды — где KV перестаёт расти линейно по контексту.
Оффлоуд KV в CPU/NVMe и деньги: $/1М токенов против облачного API.
Код лежит открыто: github.com/Isk4R1oT/ridgepoint [10]. Буду рад звезде, а ещё больше — issue с моделью, на которой мои числа разошлись с вашим vLLM.
Вопрос к тем, кто гоняет vLLM в проде: сверьте # GPU blocks из своего лога старта с тем, что предскажет ridgepoint fit на вашей модели. Совпало? И ловили ли OOM там, где по расчёту всё влезало?
Автор: Isk4R1oT
Источник [11]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/35158
URLs in this post:
[1] память: http://www.braintools.ru/article/4140
[2] arXiv:2309.06180: https://arxiv.org/abs/2309.06180
[3] ошибкой: http://www.braintools.ru/article/4192
[4] внимания: http://www.braintools.ru/article/7595
[5] arXiv:2405.04434: https://arxiv.org/abs/2405.04434
[6] calibration/CALIBRATION.md: https://github.com/Isk4R1oT/ridgepoint/blob/main/calibration/CALIBRATION.md
[7] apxml: https://apxml.com/tools/vram-calculator
[8] NyxKrage: https://huggingface.co/spaces/NyxKrage/LLM-Model-VRAM-Calculator
[9] smcleod: https://smcleod.net/vram-estimator/
[10] github.com/Isk4R1oT/ridgepoint: https://github.com/Isk4R1oT/ridgepoint
[11] Источник: https://habr.com/ru/articles/1079788/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1079788
Нажмите здесь для печати.