Внутреннее устройство vLLM: как работает высокопроизводительный инференс LLM
Hacker News · оригинал
Материал подготовлен автоматизированной редакционной системой. Факты можно сверить по указанному первоисточнику.

Статья детально разбирает архитектуру vLLM, объясняя механизмы планирования, paged attention и непрерывного батчинга. Материал описывает продвинутые функции, такие как кэширование префиксов и chunked prefill, которые оптимизируют задержку и пропускную способность при обслуживании запросов.
Ценность: Понимание низкоуровневых механизмов vLLM критически важно для инженеров, стремящихся оптимизировать стоимость и скорость генерации в продакшен-средах. Разбор показывает, как аппаратные ограничения GPU преодолеваются через эффективное управление памятью и планирование задач.
Современные системы инференса больших языковых моделей требуют сложной архитектуры для обеспечения высокой пропускной способности при приемлемых задержках. В статье рассматривается vLLM как эталонный пример такой системы, начиная с базового офлайн-режима и постепенно переходя к многопоточному онлайн-обслуживанию. Автор использует подход «перевёрнутой пирамиды», чтобы сначала сформировать целостную ментальную модель, а затем углубиться в детали конкретных подсистем.
Ядром системы выступает движок (engine), который включает в себя планировщик, менеджер KV-кэша и исполнитель модели. В отличие от простых синхронных скриптов, vLLM поддерживает непрерывный батчинг (continuous batching). Это позволяет смешивать запросы на префилл (обработка входного промпта) и декодирование (генерация токенов) в одном шаге выполнения. Планировщик приоритизирует уже запущенные запросы, но может принимать новые, если для них хватает ресурсов видеопамяти.
Ключевой инновацией является paged attention. Менеджер KV-кэша управляет памятью не как единым массивом, а блоками по 16 токенов. Это устраняет фрагментацию памяти и позволяет эффективно использовать VRAM. Когда блоки заканчиваются, система может применять механизм прерывания (preemption), высвобождая ресурсы менее приоритетных запросов для обслуживания новых или критически важных задач.
Для обработки длинных промптов используется техника chunked prefill. Вместо того чтобы блокировать весь движок на один длинный запрос, его обработка разбивается на части. Это предотвращает ситуацию, когда один пользователь задерживает генерацию для всех остальных. Реализация проста: ограничивается количество новых токенов на каждом шаге, а остальная логика индекса берёт на себя менеджер кэша.
Функция prefix caching позволяет избегать повторных вычислений общих префиксов в разных запросах. Система хеширует блоки токенов и сохраняет их в памяти. При поступлении нового запроса с тем же началом движок находит совпадения и переиспользует уже вычисленные KV-векторы. Это значительно ускоряет этап префилла, особенно в сценариях, где пользователи используют общие системные промпты или контексты.
На этапе выполнения forward pass все последовательности объединяются в один «супер-батч». Благодаря использованию масок внимания и точных позиционных индексов каждая последовательность взаимодействует только со своими токенами. Это позволяет избежать необходимости выравнивания (padding), что было бы крайне неэффективно при разнице в длине промптов. Для снижения накладных расходов на запуск ядер GPU применяются CUDA Graphs, которые записывают последовательность операций и воспроизводят их как единый блок.
Статья также затрагивает такие продвинутые темы, как guided decoding с использованием конечных автоматов для структурированного вывода и speculative decoding. Эти функции расширяют возможности базового движка, позволяя гарантировать формат ответа или ускорять генерацию за счёт предсказания нескольких токенов сразу. Все эти компоненты работают в связке, создавая систему, способную обслуживать тысячи одновременных запросов с минимальными потерями производительности.