Первый пост из серии разбирает устройство vLLM — движка для высоконагруженного инференса больших языковых моделей. Разбор опирается на коммит 42172ad от 9 августа 2025 года. Основной фокус — движок V1; V0 уже deprecated, но многие его концепции перекочевали в новый.
В минимальном offline-сценарии движок создаётся объектом LLM, а затем вызывается generate(). Конструктор состоит из конфига, processor, клиента engine core (в примере — InprocClient) и output processor. Внутри engine core живут Model Executor, Structured Output Manager, Scheduler и KV cache manager. Scheduler работает с очередями waiting и running, политики — FCFS или priority. KV cache manager держит пул блоков free_block_queue: один блок хранит 16 токенов, размер блока для стандартного transformer считается как 2 * block_size * num_kv_heads * head_size * bytes на dtype. При инициализации Worker проверяет VRAM, грузит веса, зовёт model.eval(), опционально torch.compile(), делает профилирующий проход и выделяет KV-cache, а затем снимает CUDA graphs.
На каждом шаге движок выполняет три стадии: schedule, forward pass и postprocess. Scheduler приоритезирует decode-запросы из running-очереди, затем берёт prefill из waiting, вызывает allocate_slots и обновляет токен-бюджет. Декод и префилл имеют разные профили: первый упирается в memory bandwidth, второй — в compute. В V1 их можно смешивать в одном шаге; в V0 приходилось выполнять только один тип за раз. Continuous batching работает даже в синхронном режиме: после каждого шага движок снова смотрит на все запросы, а forward pass схлопывает батч в одну super sequence, где каждая последовательность ходит только в свои токены. Во время forward pass можно использовать либо eager PyTorch, либо заранее записанные CUDA graphs.
Дальше идут продвинутые фичи. Chunked prefill режет длинные промпты на куски и не даёт одному запросу захватить весь шаг. Prefix caching переиспользует KV-cache для одинаковых начал промптов: vLLM хэширует блоки по 16 токенов, находит совпадения в cached_block_hash_to_block и не пересчитывает эти токены. Guided decoding ограничивает выбор токенов грамматикой через FSM: бэкенды вроде xgrammar строят битовую маску разрешённых токенов, запрещённым лог-вероятностям ставится -∞. Speculative decoding использует маленькую draft-модель, которая предлагает k токенов, большая модель проверяет их одной передачей и принимает или отклоняет по вероятностям; в V1 вместо отдельной draft-LLM есть n-gram, EAGLE и Medusa. Disaggregated P/D разделяет prefill и decode: prefill-инстансы пишут KV-cache, decode-инстансы читают его. В vLLM для этого есть коннекторы: для объяснения механики используют SharedStorageConnector, а LMCache на NVIDIA NIXL считается продакшн-вариантом, но он пока сыроват и с багами.