Драма двух гигантов: скорость против гибкости
Если ты когда-нибудь пытался запустить LLM локально, ты знаешь эту боль. vLLM летает — до 5x быстрее llama.cpp на том же железе за счёт PagedAttention и эффективного батчинга. Но есть нюанс: vLLM из коробки не понимает GGUF, а значит, с десятками тысяч готовых квантизаций из Hugging Face ты пролетаешь. llama.cpp, напротив, — король GGUF, но его производительность в многопользовательских сценариях заметно хуже.
Суть дилеммы: хочешь скорость — жертвуешь квантизациями. Хочешь квантизации — жертвуешь скоростью. Или нет?
К концу мая 2026 года ситуация не только не упростилась, но и обострилась. vLLM v2.0 (да, тот самый гигантский релиз начала года) поставил рекорды по throughput, а llama.cpp оброс MTP (multi-token prediction) и достиг невиданной эффективности на CPU. Но каждый инструмент всё ещё хромает в своей противоположной нише. В этой статье я покажу, как обмануть систему и получить и то, и другое.
Почему vLLM быстрее (но не всё так радужно)
Секрет скорости vLLM — PagedAttention и батчинг на лету. Вместо того чтобы перевыделять память под каждый новый токен, vLLM работает с блоками (page), что резко снижает фрагментацию и позволяет динамически группировать запросы. На практике это даёт до 5x прироста на H100 и до 3x на потребительских GPU, как я уже разбирал в статье "Токенов в секунду мало?".
Однако vLLM поддерживает только ограниченный набор квантизаций: AWQ, GPTQ (через Marlin), FP8, BitsAndBytes. GGUF, GPTQ-sliced, SpQR, HQQ — нет. И вот здесь начинается самое интересное.
Обходной путь №1: конвертация GGUF обратно в FP16
Самый прямолинейный способ: взять готовую GGUF-модель, разквантизировать её до FP16, затем загрузить в vLLM. Звучит кощунственно (зачем мы вообще квантизировали?), но иногда это единственный способ, если модель доступна только в GGUF. Например, авторские fine-tune на локальных LLM часто выкладывают только в GGUF.
1 Конвертация с помощью llama.cpp
# Скачиваем модель (пример: Qwen3-7B GGUF Q4_K_M)
wget https://huggingface.co/Qwen/Qwen3-7B-GGUF/resolve/main/qwen3-7b-q4_k_m.gguf
# Конвертируем в FP16 .safetensors
python convert_gguf_to_safetensors.py --input qwen3-7b-q4_k_m.gguf --output ./qwen3-fp16
# Загружаем в vLLM
python -m vllm.entrypoints.openai.api_server --model ./qwen3-fp16 --dtype float16Внимание: Размер модели после конвертации вырастет в 4-5 раз относительно GGUF. Если у вас 32 ГБ VRAM, Q4_K_M модели 7B (~5 ГБ) превращается в ~14 ГБ. Не подойдёт для видеокарт с 8-12 ГБ.
При этом качество остаётся FP16, то есть даже лучше, чем исходная квантизация. Но польза от этого сомнительна, ведь мы теряем преимущества квантизации. Этот метод — крайняя мера, когда модель больше нигде не найти.
Обходной путь №2: используйте AWQ или GPTQ с самого начала
Гораздо умнее — брать модель уже в формате, который понимает vLLM. Комьюнити наконец-то стало массово выкладывать AWQ-версии популярных моделей. Например, практически вся линейка Qwen3 (вышла в апреле 2026) имеет официальные AWQ чекпоинты. vLLM поддерживает AWQ из коробки через движок Marlin, что даёт скорость, близкую к FP16, при 4-битной квантизации.
# Запускаем Qwen3-7B-AWQ
docker run --gpus all -v /models:/models vllm/vllm-openai:latest
--model /models/Qwen3-7B-AWQ
--quantization awq_marlin
--max-model-len 32768Если AWQ нет, ищите GPTQ с Marlin. Но тут засада: не все GPTQ-модели работают с Marlin — нужна специальная разметка (group size 128, sym True). Как выбирать, описано в полном гайде по квантованию в vLLM.
Обходной путь №3: Unsloth — квантизация под любой формат
Unsloth — это модный инструмент, который позволяет конвертировать модели (в том числе GGUF) в поддерживаемые vLLM форматы на лету, да ещё и с дообучением. В 2026 году вышла версия 2.5, которая умеет напрямую генерировать AWQ/Marlin-совместимые чекпоинты из любого исходного формата. Больше не нужно мучиться с промежуточной конвертацией.
from unsloth import FastLanguageModel
from utils import convert_to_awq_marlin
model, tokenizer = FastLanguageModel.from_pretrained(
"unsloth/Qwen3-7B-bnb-4bit", # например, BitsAndBytes 4-bit
load_in_4bit=True,
)
# Конвертируем в AWQ для vLLM
convert_to_awq_marlin(model, output_dir="./qwen3-awq-marlin")Обходной путь №4: динамический батчинг на llama.cpp с MTP
А что, если мы хотим оставить квантизации GGUF, но ускорить сам llama.cpp? В ноябре 2025 llama.cpp ввёл Multi-Token Prediction (MTP) — предсказание нескольких токенов за один проход. Бета-версия уже показывала прирост до 30% на длинных последовательностях. В мае 2026 MTP стабилизировался и работает с любыми моделями, поддерживающими speculative decoding.
Как включить MTP, я подробно описал в гайде по MTP. С ним llama.cpp может догнать vLLM в однопользовательских сценариях, но всё ещё уступает при параллельных запросах. В связке с сравнением Q4_K_M vs Q8_0 видно, что правильный выбор квантизации может добавить ещё 10-15%.
Обходной путь №5: vLLM с BitsAndBytes 4-bit
Если GPU позволяет (>= 16 ГБ), можно загрузить модель в vLLM с 4-битной квантизацией через BitsAndBytes. Это не так быстро, как AWQ (на ~20-30% медленнее), но всё равно быстрее llama.cpp. И не требует конвертации — подходит любой safetensors. Баг: BnB 4-bit пока не поддерживает Marlin, так что используйте старый метод.
vllm serve meta-llama/Llama-4-8B-Instruct
--quantization bitsandbytes
--load-format bitsandbytes
--dtype float16Важно: vLLM 2.0 исправила проблему с фрагментацией памяти при BnB, поэтому теперь можно работать с контекстом до 64K токенов. Однако на старых картах вроде Tesla P40 BnB может вылетать из-за нехватки инструкций.
Практический чек-лист: что выбрать под свою задачу
| Сценарий | Рекомендация | Ожидаемый прирост скорости |
|---|---|---|
| Модель только в GGUF, нужно быстро | Конвертация GGUF -> FP16 -> vLLM | До 3x vs llama.cpp GGUF |
| Модель есть в AWQ/GPTQ | vLLM напрямую с awq_marlin | До 5x vs llama.cpp |
| Хочу GGUF, но и скорость важна | llama.cpp с MTP + Q4_K_M | ~1.5x vs базовая llama.cpp |
| Есть время на дообучение/конвертацию | Unsloth -> AWQ | До 4.5x vs llama.cpp |
| Ограниченный VRAM | vLLM + BitsAndBytes 4bit | ~2x vs llama.cpp |
Подводные камни и ошибки, которые я совершал
- Не учитывать TCO. vLLM требует больше VRAM (FP16 vs GGUF). Если GPU всего 16 ГБ, FP16 модель 13B не влезет. Считайте: (параметры в B) * 2 байта / 1e9 — это минимум для FP16. GGUF Q4 занимает в 4 раза меньше.
- Путать форматы квантизации. Marlin не работает с group size != 128 или sym=False. Если GPTQ-модель не поддерживает Marlin, vLLM упадёт с ошибкой. Всегда проверяйте
config.json. - Забывать про alpha_value / max_model_len. vLLM по умолчанию режет контекст. Если вы используете модель с контекстом 128K, задавайте
--max-model-lenявно. Иначе скорость упадёт из-за реаллокации. - Не тестировать на своей архитектуре. Как я писал в статье про Ubuntu и llama.cpp, на Linux vLLM работает на 10-15% быстрее, чем на Windows, из-за лучшей работы с CUDA memory pool.
- Игнорировать Post-Training Quantization degradation. Если ваша модель используется для сложного chain-of-thought, квантизация может ломать логику. В моём исследовании показано, что Q4_K_M теряет до 8% точности на длинных рассуждениях. Лучше пожертвовать скоростью и взять Q5_K_M или FP8.
Реальный пример конфигурации
Возьмём типовую задачу: чат-бот на базе Qwen3-7B для 50 одновременных пользователей на одном H100 (80 ГБ).
# Пример запуска production-ready vLLM с AWQ
docker run --gpus all --shm-size=32g
-v /models:/models
vllm/vllm-openai:latest
--model /models/Qwen3-7B-AWQ
--quantization awq_marlin
--max-model-len 65536
--gpu-memory-utilization 0.95
--max-num-seqs 256
--enable-prefix-cachingЭто даёт стабильную работу с 50 параллельными пользователями, каждый с контекстом до 8K. Среднее время до первого токена — 80 мс. Нагрузка на GPU — ~85%.
Альтернатива: не изобретать велосипед — облачные инференс-сервисы
Если у тебя нет доступа к мощному GPU или лень разбираться с квантизациями, можно арендовать уже настроенный инференс-сервер. Например, сервисы вроде RunPod или Vast.ai позволяют развернуть vLLM в один клик. Однако стоимость за час может быть выше, чем покупка своего GPU — считайте TCO.
Итог: скорость и квантизации больше не враги
Основная идея простая: не нужно выбирать между vLLM и llama.cpp. Если ты можешь потратить 10 минут на скачивание AWQ-модели — бери vLLM. Если модель есть только в GGUF и ты не хочешь терять VRAM — используй llama.cpp с MTP. Есть и компромисс: BitsAndBytes в vLLM даёт квантизацию без потери скорости, хоть и не такую сильную.
Мой прогноз на конец 2026 года: ждём нативной поддержки GGUF в vLLM. Слухи ходят, что в vLLM 2.1 появится экспериментальный бэкенд для GGUF на основе ggml. Но пока этого нет, описанные выше обходные пути — твой джентльменский набор.
И напоследок: если ты всё ещё используешь llama.cpp без MTP на CPU — прочитай гайд по сборке llama.cpp. Ты удивишься, насколько быстрее может работать твой процессор, если включить правильные флаги BLAS.