Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → vLLM: производительный сервинг LLM

vLLM: как устроен эффективный сервинг LLM и что настраивать

vLLM: PagedAttention и continuous batching, параметры gpu-memory-utilization и max-num-seqs, метрики throughput и задержки, типовые ошибки настройки.

Прямой ответ

vLLM — движок инференса LLM, ориентированный на пропускную способность. Два механизма дают основной выигрыш:

  1. PagedAttention. KV-кэш хранится не непрерывным блоком на запрос, а «страницами», как виртуальная память в ОС. Это убирает фрагментацию: при классическом подходе значительная часть выделенной памяти под кэш простаивает, потому что длина ответа заранее неизвестна.
  2. Continuous batching (непрерывное батчингирование). Запросы добавляются в выполняющийся батч по мере поступления, а завершившиеся освобождают место немедленно, не дожидаясь конца всей группы. Это резко повышает утилизацию GPU при разнородных запросах.

Практический смысл: на одной и той же видеокарте vLLM обслуживает в разы больше одновременных запросов, чем наивный поштучный инференс, — ценой более сложной настройки и требовательности к VRAM.

Базовый запуск OpenAI-совместимого сервера:

python -m vllm.entrypoints.openai.api_server \
  --model Qwen/Qwen2.5-7B-Instruct \
  --dtype auto \
  --max-model-len 8192 \
  --gpu-memory-utilization 0.90 \
  --max-num-seqs 64 \
  --port 8000

Ключевые параметры:

  • --gpu-memory-utilization — доля VRAM, которую движок забирает под веса и KV-кэш. Слишком высокое значение оставляет память под фрагментацию и служебные буферы и приводит к OOM.
  • --max-model-len — максимальная длина контекста (вход + выход). Прямо определяет, сколько страниц кэша нужно на запрос.
  • --max-num-seqs — максимум одновременных последовательностей в батче.
  • --tensor-parallel-size — распараллеливание модели на несколько GPU.

Практика: метрики и настройка под нагрузку

vLLM отдаёт метрики в формате Prometheus на /metrics. Минимально необходимый набор:

  • число ожидающих и выполняющихся запросов;
  • использование KV-кэша (доля занятых блоков);
  • время до первого токена (TTFT) и время на токен (TPOT/ITL);
  • количество прерванных (preempted) запросов.

Как интерпретировать:

  1. KV-кэш заполнен, растёт число preempted. Значит, запросов больше, чем памяти на их контексты. Решения: снизить --max-model-len, уменьшить --max-num-seqs, добавить GPU или взять квантованную модель.
  2. TTFT растёт, GPU утилизирован не полностью. Часто причина в длинных входных промптах и недостаточном параллелизме префилла; помогает увеличить размер батча и проверить, не упирается ли подача запросов в клиент.
  3. Утилизация GPU низкая при малой нагрузке. Это норма: continuous batching раскрывается под нагрузкой. Оценивать конфигурацию нужно на целевом RPS, а не на одном запросе.

Рекомендации:

  1. Измеряйте перцентили, а не среднее. Среднее время ответа маскирует деградацию в хвосте; как строить гистограммы и p95 — в статье про перцентили метрик.
  2. Разделяйте префилл и генерацию в измерениях. Пользователь воспринимает TTFT как «отвисает», а TPOT — как «медленно печатает». Это разные проблемы с разными решениями.
  3. Фиксируйте версию движка. Поведение планировщика и метрик меняется между релизами; обновление vLLM стоит проверять на своём нагрузочном профиле.
  4. Оставляйте запас VRAM. Практика: --gpu-memory-utilization 0.85–0.92 и проверка, что пиковая нагрузка не вызывает OOM.

Что проверять при смене версии движка. Прогоните фиксированный набор запросов и сравните три показателя: долю корректных ответов, p95 времени до первого токена и пропускную способность при целевой конкуренции. Расхождение по качеству означает изменение поведения генерации, а не только производительности, и требует отдельного разбора перед выкладкой.

Практический сценарий: сервис «захлёбывается» в час пик

Контекст: внутренний ассистент на vLLM, один GPU 24 ГБ, модель 7B, --max-model-len 32768. В пике пользователи ждут ответа минутами.

  1. Диагностика. В метриках: использование KV-кэша 100 %, число preempted запросов растёт, очередь ожидает. Причина — слишком большой заявленный контекст: движок резервирует блоки под 32K токенов на запрос, хотя фактически используются 3–6K.
  2. Проверка фактических длин. По логам запросов: p95 входа — 2.4K токенов, p95 выхода — 400 токенов.
  3. Исправление. Ставим --max-model-len 8192, увеличиваем --max-num-seqs до 96, оставляем --gpu-memory-utilization 0.90. На стороне клиента добавляем обрезку истории диалога.
  4. Результат. Одновременных запросов обслуживается втрое больше, p95 TTFT падает с 40 с до 3 с, preempted исчезают.
  5. Профилактика. Добавляем алерты на заполнение KV-кэша выше 90 % и на рост preempted; в runbook фиксируем процедуру снижения лимитов — как оформлять такие инструкции, см. incident management и runbook.

Вывод: в vLLM пропускная способность определяется памятью под KV-кэш, а она расходуется пропорционально заявленной длине контекста. Занижать фактические потребности так же вредно, как завышать лимиты.

FAQ

Когда vLLM избыточен и достаточно llama.cpp? Для одного-двух пользователей и локальной разработки достаточно llama-server. vLLM оправдан при десятках одновременных запросов, когда важна пропускная способность на единицу стоимости GPU.

Поддерживает ли vLLM квантованные модели? Да: AWQ, GPTQ, FP8 и другие схемы, в зависимости от версии движка. Квантование уменьшает объём весов и освобождает VRAM под KV-кэш, что напрямую увеличивает допустимый параллелизм.

Что такое preempted запросы? Когда памяти на KV-кэш не хватает, планировщик вытесняет часть последовательностей, чтобы продолжить другие. Вытесненный запрос либо пересчитывается позже, либо восстанавливается из выгруженного кэша. Рост числа вытеснений — явный признак нехватки памяти под контексты.

Как масштабировать дальше одной видеокарты? Варианты: --tensor-parallel-size для разделения одной модели на несколько GPU, либо несколько независимых инстансов за балансировщиком. Второй вариант проще эксплуатировать и даёт предсказуемую деградацию при отказе одного инстанса; оценку требуемого числа инстансов делают через capacity planning.

Источники: vLLM docs, PagedAttention paper, vLLM OpenAI server docs — ссылки в шапке.