Сколько памяти нужно для vLLM
vLLM не берёт память «по мере надобности» — он на старте забирает заданную долю карты и раскладывает её по полкам, поэтому либо запускается сразу, либо падает на первой секунде с длинным ValueError. Ниже — как посчитать бюджет до заказа железа: формула KV-кэша, таблица по моделям, роль системной RAM и точные тексты ошибок.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Короткий ответ: сколько памяти требует vLLM
Требования vLLM распадаются на два вопроса. Сколько VRAM нужно, чтобы движок стартовал — веса плюс рабочий буфер. Сколько нужно, чтобы он держал нагрузку — KV-кэш, растущий от длины контекста и числа одновременных запросов.
Ориентиры при контексте 8192 токена и восьми параллельных запросах:
| Модель | Формат | Веса | Минимум VRAM | Комфорт |
|---|---|---|---|---|
| Qwen2.5 7B Instruct | FP16 | 15,2 ГБ | 24 ГБ | 24 ГБ |
| Llama 3.1 8B Instruct | FP16 | 16,1 ГБ | 24 ГБ | 32–48 ГБ |
| Llama 3.1 8B Instruct | AWQ 4-бит | ~5,7 ГБ | 12 ГБ | 24 ГБ |
| Qwen2.5 14B | FP16 | 29,5 ГБ | 48 ГБ | 2×24 ГБ, TP=2 |
| Qwen2.5 32B | AWQ 4-бит | ~19,4 ГБ | 24 ГБ, контекст 4k | 48 ГБ |
| Llama 3.3 70B | AWQ 4-бит | ~40 ГБ | 48 ГБ | 80 ГБ |
| Llama 3.3 70B | FP16 | ~141 ГБ | 2×80 ГБ | 4×48 ГБ |
Системной памяти нужно примерно объём весов плюс 8–16 ГБ и не меньше 16 ГБ в любом случае — почему так, в четвёртой секции. Правило стоит запомнить одно: после весов на карте должно остаться под KV-кэш не меньше, чем max_model_len × байт_на_токен × число одновременных запросов. Меньше — vLLM либо не стартует, либо начнёт вытеснять запросы.
Четыре слагаемых бюджета VRAM
Память карты делится на четыре части — лечатся они разными флагами.
- Веса. Параметры на байт на параметр: FP16 и BF16 — 2 байта, FP8 и INT8 — 1, AWQ и GPTQ в 4 битах — около 0,5 плюс 10–15 % на масштабы. Отсюда 8,03 млрд параметров Llama 3.1 8B дают 16,1 ГБ в FP16 и 5,7 ГБ в AWQ.
- KV-кэш. Единственная часть, зависящая от нагрузки. Весь остаток бюджета движок отдаёт под него на старте — целиком и сразу, страницами по 16 токенов.
- Активации. Профилировочный прогон: vLLM считает фиктивный батч на
--max-num-batched-tokensтокенов и смотрит пик. Для 8B — порядка 1–2 ГБ. - CUDA-графы. Захватываются на старте под набор размеров батча: от гигабайта до двух-трёх, отключаются флагом
--enforce-eager.
Главная механика, о которую спотыкаются: --gpu-memory-utilization — доля от полной ёмкости карты, а не от свободной. По умолчанию 0,9 на карте 24 ГБ означает бюджет около 21,6 ГБ на всё вместе, и занятое чужим процессом вычитается из него:
nvidia-smi --query-gpu=memory.total,memory.used,memory.free --format=csv
nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv
Итоговая арифметика такая:
KV-кэш = ёмкость карты × gpu-memory-utilization − веса − активации − графы
Считать вручную не обязательно, движок печатает результат при старте:
INFO [gpu_worker.py:298] Available KV cache memory: 4.23 GiB
INFO [kv_cache_utils.py:864] GPU KV cache size: 34,608 tokens
INFO [kv_cache_utils.py:868] Maximum concurrency for 8,192 tokens per request: 4.22x
Последняя строка — самая полезная во всём логе. 4.22x значит: при --max-model-len 8192 движок вытянет чуть больше четырёх полностью заполненных диалогов. Нужно двадцать — считайте это цифрой отказа. В старом V0 то же печаталось строкой # GPU blocks: 2163, блоки по 16 токенов; V1 — движок по умолчанию с 0.8, и в свежих ветках V0 уже вырезан.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверФормула KV-кэша и таблица по моделям
KV-кэш считается точно, без эмпирики:
байт на токен = 2 (ключи и значения) × число слоёв × число KV-голов × размер головы × байт на элемент
Все четыре числа лежат в config.json модели: num_hidden_layers, num_key_value_heads, head_dim (если его нет — hidden_size / num_attention_heads). Считается одной строкой на сервере:
python3 -c "
import json,sys
c=json.load(open(sys.argv[1]))
h=c.get('head_dim') or c['hidden_size']//c['num_attention_heads']
b=2*c['num_hidden_layers']*c['num_key_value_heads']*h*2
print(f'{b} байт/токен = {b/1024:.0f} КиБ; в 1 ГиБ помещается {1073741824//b} токенов')
" ~/.cache/huggingface/hub/models--Qwen--Qwen2.5-7B-Instruct/snapshots/*/config.json
Готовые значения для FP16:
| Модель | Слои | KV-головы | Размер головы | КиБ на токен | Токенов в 1 ГиБ |
|---|---|---|---|---|---|
| Qwen2.5 7B | 28 | 4 | 128 | 56 | ~18 700 |
| Llama 3.1 8B | 32 | 8 | 128 | 128 | 8 192 |
| Mistral 7B v0.3 | 32 | 8 | 128 | 128 | 8 192 |
| Qwen2.5 14B | 48 | 8 | 128 | 192 | ~5 460 |
| Qwen2.5 32B | 64 | 8 | 128 | 256 | 4 096 |
| Gemma 2 9B | 42 | 8 | 256 | 336 | ~3 120 |
| Llama 3.3 70B | 80 | 8 | 128 | 320 | ~3 280 |
Разброс в шесть раз между Qwen2.5 7B и Gemma 2 9B при почти одинаковых весах: число KV-голов важнее числа параметров, и планировать, не заглянув в конфиг, — способ промахнуться. Две поправки: Gemma 2 использует скользящее окно на половине слоёв, и на контексте длиннее 4096 расход ниже табличного; MoE считается по полному числу параметров — Mixtral 8x7B это 46,7 млрд и около 93 ГБ в FP16, хотя активных на токен 13 млрд.
Практический расчёт. Llama 3.1 8B в FP16 на карте 24 ГБ: бюджет при 0,9 — 21,6 ГБ, минус 16,1 ГБ весов и около 1,5 ГБ на активации и графы. Остаётся ~4 ГБ, то есть ~32 000 токенов кэша: четыре диалога при --max-model-len 8192 или восемь при 4096. А паспортные 131 072 токена контекста требуют 16 ГиБ кэша на один запрос — отсюда ошибка первого запуска.
Системная RAM: сколько её нужно и на что она уходит
Про VRAM пишут все, про хостовую память — почти никто, а именно на ней ломается половина первых запусков.
- Загрузка весов. vLLM читает safetensors через
mmap, поэтому пик анонимной памяти обычно ниже размера модели, но страничный кэш забьётся под завязку. Хуже, когда RAM меньше весов и включён своп: загрузка 16-гигабайтной модели превращается в своп-шторм, аvllm serveвыглядит зависшим. Правило: RAM не меньше объёма весов плюс 8 ГБ. - Процессы. При
--tensor-parallel-size 2и выше на каждую карту поднимается воркер со своим CUDA-контекстом и экземпляром PyTorch — ещё по 0,5–1,5 ГБ. - Буфер вытеснения. У флага
--swap-spaceзначение по умолчанию — 4 ГиБ хостовой памяти на карту. В V1 вытеснение сделано пересчётом, но заложить буфер стоит. - Разделяемая память в Docker. Официальный образ получает
/dev/shmв 64 МБ, а межпроцессное взаимодействие PyTorch идёт через него. При--tensor-parallel-sizeбольше единицы это кончается падениемBus error (core dumped)или сообщениемUnexpected bus error encountered in worker. This might be caused by insufficient shared memory (shm). Лечится флагом--shm-size=16gили--ipc=host. - CPU-бэкенд. Там KV-кэш живёт в обычной памяти и задаётся не долей, а числом гигабайт в переменной
VLLM_CPU_KVCACHE_SPACE(по умолчанию 4 ГиБ).
Честно про CPU: этот бэкенд существует для разработки, а не для продакшена — непрерывный батчинг и PagedAttention без видеокарты не работают. Для процессорного инференса берите Ollama или llama.cpp. Порядок цифр с нашего стенда AMD EPYC 9554 (16 vCPU — 8 физических ядер плюс HT): Ollama 0.33.1 с qwen2.5:7b в Q4_K_M даёт 7,6 токена в секунду на 4 и на 8 потоках и 7,4 на 16 — полка наступает рано, упор идёт в пропускную способность памяти, а не в ядра. А num_thread 32 на тех же 16 vCPU роняет генерацию до 0,35 ток/с, в двадцать раз. Подробнее — Ollama против vLLM и таблица памяти Ollama.
Про диск строкой: pip install vllm тянет PyTorch с библиотеками CUDA — 8–10 ГБ, плюс кэш весов. Задайте отдельный том через HF_HOME=/mnt/data/hf, иначе раздел на 40 ГБ кончится на второй модели.
Что происходит при нехватке: точные ошибки
По тексту сразу видно, какое из четырёх слагаемых не поместилось.
Не хватило на KV-кэш при старте — самая частая ошибка вообще:
ValueError: To serve at least one request with the models's max seq len (131072),
(16.00 GiB KV cache is needed, which is larger than the available KV cache memory
(4.23 GiB). Based on the available memory, you can try increasing
`gpu_memory_utilization` or decreasing `max_model_len` when initializing the engine.
Совет из самого текста ошибки вводит в заблуждение: поднимать gpu_memory_utilization с 0,9 почти некуда. Лечение — --max-model-len 8192.
Не хватило ни на что. Веса и активации съели весь бюджет:
ValueError: No available memory for the cache blocks. Try increasing
`gpu_memory_utilization` when initializing the engine.
Модель в карту в текущем формате не влезает; флагами не чинится — нужно квантование или карта больше.
Упало на профилировочном прогоне — классический OOM от PyTorch:
torch.OutOfMemoryError: CUDA out of memory. Tried to allocate 2.00 GiB. GPU 0 has a
total capacity of 23.65 GiB of which 108.06 MiB is free. Process 3142 has 23.53 GiB
memory in use. Of the allocated memory 22.71 GiB is allocated by PyTorch, and
45.62 MiB is reserved by PyTorch but unallocated.
Смотрите на Process ... has ... memory in use: если PID не ваш, на карте посторонний процесс. Если ваш — уменьшайте --max-num-seqs.
Кончилась хостовая память. Тут vLLM не падает с трейсбеком, а исчезает — процесс убивает ядро:
dmesg -T | grep -i "killed process"
# Out of memory: Killed process 14822 (VLLM::EngineCore) total-vm:64213524kB, anon-rss:31204880kB
Если в journalctl -u vllm последняя строка — обычный INFO про загрузку весов, причина здесь. Разбор — что делать при нехватке RAM.
Памяти хватило, но её мало. Движок стартовал, а под нагрузкой вытесняет запросы:
WARNING Sequence group 42 is preempted by PreemptionMode.RECOMPUTE mode because
there is not enough KV cache space. This can affect the end-to-end performance.
Increase gpu_memory_utilization or tensor_parallel_size to provide more KV cache.
curl -s http://127.0.0.1:8000/metrics | grep -E 'num_preemptions_total|gpu_cache_usage_perc'
Растущий vllm:num_preemptions_total и vllm:gpu_cache_usage_perc около единицы означают переполненный кэш: запросы пересчитываются с нуля, латентность скачет. Тюнингом не лечится — либо короче контекст, либо больше VRAM.
Как ужать: рычаги по убыванию эффекта
Порядок неслучайный — первые два обычно закрывают вопрос.
--max-model-len. Режет кэш линейно: со 131 072 до 8192 — экономия в шестнадцать раз. Ставьте столько, сколько нужно самому длинному диалогу плюс ответу.- Квантование весов. AWQ или GPTQ в 4 битах освобождают на 8B около 10 ГБ, то есть утраивают кэш. На инструктивных задачах качество падает мало, на длинных документах разница видна.
--kv-cache-dtype fp8. Ровно вдвое дешевле кэш. Аппаратная поддержкаfp8_e4m3есть на Ada и Hopper (compute capability 8.9 и выше), на Ampere проверяйте сборку, а на T4 и V100 движок стартует только с--dtype half.--max-num-seqsи--max-num-batched-tokens. По умолчанию щедро, сотни последовательностей; снижение до 32–64 срезает пик активаций. Что стоит у вас:vllm serve --help | grep -A3 'max-num-seqs'.--enforce-eager. Отдаёт гигабайт-два, отобранные CUDA-графами, ценой латентности.--gpu-memory-utilizationдо 0,92–0,95. Требует, чтобы карта была вашей целиком: при 0,97 первый всплеск фрагментации даёт OOM уже в рантайме.--tensor-parallel-size 2. Делит между картами и веса, и кэш; нужен увеличенный/dev/shm.--cpu-offload-gb. Выносит часть весов в RAM, но каждый форвард-проход тянет их обратно по PCIe. Аварийная мера, не конфигурация.
Рабочий пример под карту 24 ГБ и модель 7B:
python3 -m venv /opt/vllm
/opt/vllm/bin/pip install "vllm==0.11.0"
HF_HOME=/mnt/data/hf /opt/vllm/bin/vllm serve Qwen/Qwen2.5-7B-Instruct-AWQ \
--host 127.0.0.1 --port 8000 \
--quantization awq_marlin \
--max-model-len 16384 \
--max-num-seqs 32 \
--kv-cache-dtype fp8 \
--gpu-memory-utilization 0.92 \
--api-key sk-local-changeme
Версию фиксируйте: между минорными релизами vLLM меняет флаги и умолчания, и конфиг с 0.9 на 0.11 может не подняться. После старта прочитайте Maximum concurrency: меньше ожидаемого пика — нагрузочный тест можно не запускать.
Какой сервер взять под vLLM в MAATRIX
Сначала честное: vLLM в каталоге apps.maatrix.io нет. Сервер приезжает чистым — Ubuntu 24.04 или Debian 12, — и движок вы ставите по инструкции выше. Автоматически при заказе ставятся родственные сервисы: Ollama, Open WebUI, LiteLLM, AnythingLLM, Qdrant. Связка рабочая: vLLM отдаёт OpenAI-совместимый эндпоинт на 127.0.0.1:8000, а перед ним стоит LiteLLM или Open WebUI из каталога с доступами в кабинете.
Честный минимум под 7–8B в FP16: GPU с 24 ГБ VRAM, 8 vCPU, 32 ГБ RAM, 100 ГБ NVMe. Ограничение называем прямо: контекст придётся держать в пределах 8192 токенов, а полноразмерных диалогов будет около четырёх. Внутреннему боту на отдел хватает, публичному сервису — нет.
Комфортный вариант: 48 ГБ VRAM одной картой или две по 24 с --tensor-parallel-size 2, 16 vCPU, 64 ГБ RAM, 200 ГБ NVMe. Здесь 8B живёт в FP16 с контекстом 32k и десятками параллельных запросов, а 32B — в AWQ.
Модели 70B требуют 80 ГБ VRAM одной картой в 4-битном квантовании либо нескольких карт. Посчитайте по формуле из третьей секции, влезет ли контекст: кэш там стоит 320 КиБ за токен. Как подбирать карту под несколько пользователей — в разборе выбор GPU-сервера.
Без видеокарты vLLM брать не стоит: возьмите VPS с 8 vCPU и 32 ГБ RAM под Ollama. 7–8B в Q4 даст около 8 токенов в секунду — боту и фоновой обработке документов хватит, живому чату нет.
Локация — UK, Лондон. HuggingFace оттуда открывается напрямую, а загрузка весов на 16–140 ГБ через прокси из России обрывается регулярно. Плюс низкий пинг до ЕС и европейская юрисдикция, если модель обрабатывает данные клиентов из Евросоюза. RU берите под 152-ФЗ, US — если рядом стоит прокси к зарубежным API. Сравнение локаций — VPS в Великобритании для доступа к нейросетям.
Оплата — картами российских банков, по СБП, криптовалютой или токеном MAAT. Совет напоследок: прежде чем брать карту побольше, снимите vllm:num_preemptions_total и длину очереди. Часто не хватает не VRAM, а здравого --max-model-len.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Сколько системной RAM нужно, если видеокарта уже есть?
Не меньше объёма весов плюс 8 ГБ и не меньше 16 ГБ в принципе: веса читаются через страничный кэш, каждый воркер добавляет 0,5–1,5 ГБ, плюс 4 ГиБ по умолчанию на --swap-space. Для 8B в FP16 ориентир — 32 ГБ.
Почему сразу после старта nvidia-smi показывает 22 ГБ из 24 занятыми?
Так и задумано: vLLM выделяет --gpu-memory-utilization от ёмкости карты один раз при инициализации и держит эту память под KV-кэш. Фактическую занятость показывает метрика vllm:gpu_cache_usage_perc, а не драйвер.
Можно ли уменьшить память, не трогая контекст и квантование?
Да, но выигрыш скромнее: --enforce-eager вернёт гигабайт-два, --max-num-seqs 32 срежет пик активаций, --kv-cache-dtype fp8 удвоит ёмкость кэша. Если после всего Maximum concurrency меньше вашего пика — вопрос решается только объёмом VRAM.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.