Зачем LLM serving выделяют в отдельную тему
С обычной моделью часто все выглядит просто: собрали batch, сделали forward pass, вернули ответ. С LLM так думать опасно. Запрос сначала надо целиком прочитать, потом ответ рождается по одному токену, а параллельно сервис держит очередь, стримит текст пользователю, освобождает память после отмененных запросов и следит, чтобы дорогая GPU не простаивала.
Эта страница опирается не на “примерно помню”, а на несколько слоев источников: курс Stanford CS336 для общей картины inference systems, tutorial Hugging Face Transformers: Continuous Batching для механики prefill/decode, paper PagedAttention/vLLM для памяти KV-cache, SGLang docs для runtime/routing/cache reuse, BentoML LLM metrics для метрик и production-кейсы NVIDIA/Perplexity and NAVER для привязки к реальности.
| Термин | По-русски | Зачем нужен |
|---|---|---|
| Prefill | Модель читает весь prompt до первого токена ответа. | Главный вклад во время до первого токена, особенно на длинных prompt. |
| Decode | Модель добавляет ответ по одному токену. | Долго держит запрос в памяти и упирается в KV-cache, scheduler and memory bandwidth. |
| KV-cache | Память attention для уже прочитанных токенов. | Ускоряет генерацию, но быстро ест память видеокарты. |
| Continuous batching | Сервис добавляет и убирает запросы между шагами генерации. | Поднимает загрузку GPU, но требует аккуратно следить за задержками. |
| TTFT | Время до первого токена. | То, что пользователь чувствует как “бот начал отвечать быстро или тупит”. |
| TPOT / ITL | Время между токенами. | То, насколько ровно и быстро идет стрим ответа. |
Один запрос: prefill и decode
LLM не печатает весь ответ за один проход. Сначала идет prefill: модель прогоняет prompt целиком и сохраняет промежуточную память attention. Потом начинается decode: модель берет уже накопленный контекст, предсказывает следующий токен, добавляет его в контекст и повторяет цикл. Поэтому длинный prompt и длинный ответ ломают систему по-разному.
| Сценарий | Что происходит | Какая метрика первой портится | Что смотреть |
|---|---|---|---|
| Длинный prompt, короткий ответ | Модель долго читает вход, но быстро заканчивает генерацию. | TTFT: пользователь ждет первый токен. | Prompt tokens/sec, queue wait, prefill batching, chunked prefill. |
| Короткий prompt, длинный ответ | Первый токен появляется быстро, но запрос долго висит в decode. | TPOT/ITL and active sequences. | KV-cache memory, decode throughput, max active sequences. |
| Много коротких запросов | Сервису важно быстро подсаживать новые запросы в работу. | Queue time and p95/p99. | Continuous batching, admission control, priority queues. |
| Много одинаковых системных prompt | У запросов есть общий префикс. | Cost and TTFT if prefix is recomputed. | Prefix cache hit rate and cache eviction. |
Короткая собесная формулировка
KV-cache: ускорение, которое само становится проблемой
KV-cache хранит ключи и значения attention для уже обработанных токенов. Без него на каждом новом токене пришлось бы заново пересчитывать прошлый контекст. С ним decode становится сильно дешевле. Но цена понятная: чем больше активных запросов и чем длиннее контекст, тем больше памяти видеокарты уходит на cache.
Грубая интуиция такая: память cache растет вместе с числом слоев, числом активных токенов, размерностью attention and bytes per value. Это не формула для точного sizing без учета реализации, но хороший способ понять, почему long context serving внезапно становится задачей про HBM, fragmentation and memory bandwidth, а не только про FLOPs.
PagedAttention и prefix cache
Главная идея PagedAttention из vLLM: не хранить KV-cache как один большой непрерывный кусок на каждую sequence. Запросы разной длины приходят и заканчиваются в разное время, поэтому naive allocation быстро дает пустоты и fragmentation. PagedAttention режет cache на blocks/pages и управляет ими похожим образом на virtual memory: так проще переиспользовать HBM и держать больше активных запросов.
Prefix cache - соседняя, но не та же идея. Если у многих запросов одинаковое начало, например system prompt или общий RAG-template, его можно не считать заново. В vLLM это описано в Automatic Prefix Caching docs. В SGLang похожая линия развивается через RadixAttention and hierarchical cache: она особенно интересна, когда приложение делает цепочку связанных вызовов, а не один одиночный prompt.
| Механика | Что чинит | Где легко ошибиться |
|---|---|---|
| PagedAttention | Waste and fragmentation в KV-cache при запросах разной длины. | Нельзя обещать фиксированный x-разгон: эффект зависит от модели, traffic mix and hardware. |
| Prefix caching | Повторный пересчет общего начала prompt. | Если префиксы редко совпадают или часто invalidated, пользы мало. |
| Radix/prefix reuse in SGLang | Переиспользование общих частей между связанными program-like вызовами. | Надо смотреть именно application pattern: agents/RAG/tools/structured output. |
| KV quantization / lower precision | Меньше memory pressure. | Нужно проверять качество и стабильность на своих задачах. |
Батчинг и scheduler
У классического static batch есть неприятный эффект: короткие запросы могут ждать длинные. В генерации это особенно больно, потому что один ответ может закончиться за 20 токенов, а другой будет стримиться минуту. Continuous batching решает это через scheduler: между decode steps он добавляет новые запросы, убирает завершенные и пытается держать GPU занятой.
Важно: scheduler не “бесплатно ускоряет все”. Если слишком агрессивно гнаться за throughput, можно ухудшить TTFT для новых пользователей или p99 для коротких запросов. Более продвинутые papers вроде Orca and Sarathi-Serve полезны именно этим: они показывают, что serving - это trade-off между prefill, decode, latency and throughput.
| Ручка настройки | Что она значит по-человечески | Риск |
|---|---|---|
| max model length | Какой максимальный контекст обещаем поддержать. | Большой лимит может заранее съесть память и снизить concurrency. |
| max batch tokens | Сколько токенов scheduler готов держать в одном шаге. | Можно поднять throughput и одновременно ухудшить TTFT/p99. |
| max active sequences | Сколько запросов одновременно живут в decode. | Растет KV-cache and tail latency. |
| Chunked prefill | Длинный prompt режется на куски, чтобы decode не голодал. | Сложнее scheduler и tuning; выигрыш зависит от traffic mix. |
| Priority / admission control | Кого берем в работу первым и кого не пускаем при перегрузе. | Без этого VIP/interactive traffic может страдать от bulk jobs. |
Как выбирать serving engine
vLLM, SGLang, TensorRT-LLM, Triton and TGI не стоит учить как рейтинг “кто быстрее”. Нормальный выбор начинается с вопросов: какие длины prompt/answer, нужен ли streaming, есть ли повторяющиеся префиксы, нужен ли JSON по схеме, есть ли RAG/tools/agents, сколько моделей или адаптеров надо обслуживать, какие SLO по p95/p99 and cost.
| Стек | Где уместен | Что проверять в первую очередь |
|---|---|---|
| vLLM | Хороший open-source default для OpenAI-compatible API, PagedAttention, prefix caching, structured outputs and metrics. | TTFT, TPOT/ITL, GPU cache usage, prefix cache hit rate, p95/p99 on your prompts. |
| SGLang | Multi-call workloads: agents, RAG chains, structured output, tool calls, vision-language cases, cache-aware routing. | Radix/prefix cache hit rate, router policy, structured output latency, compatibility with model family. |
| TensorRT-LLM + Triton | NVIDIA-heavy production stack, где команда готова платить сложностью ради latency/throughput/control. | Build/deploy complexity, model support, quantization path, batching policy, rollback and observability. |
| TGI | Полезный architecture reference and HF ecosystem context; особенно для legacy/migration сравнения. | Текущий статус проекта, model compatibility, metrics, стоит ли брать для greenfield. |
| LoRAX-like adapter serving | Много fine-tuned adapters/LoRA поверх общих base models. | Adapter loading, multi-adapter batching, isolation, cache behavior, vendor-specific assumptions. |
Слабый ответ на собесе
Production-кейсы: что из них вынести
- Perplexity + NVIDIA - пример search-scale serving, где важны routing, multi-model stack, throughput and cost per query. Это не универсальный benchmark, а история про конкретный workload.
- NAVER Place + TensorRT-LLM - хороший кейс для разговора про TTFT/TPOT: vertical SLM-service, где пользовательская задержка важнее абстрактного tokens/sec.
- LoRAX/Predibase - полезный vendor case про обслуживание сотен fine-tuned adapters and continuous multi-adapter batching. Это материал от вендора, поэтому берем инженерные идеи, но не используем его как независимое доказательство качества или скорости.
Как читать материалы по порядку
| Шаг | Источник | Что забрать |
|---|---|---|
| 1 | Stanford CS336 and HF continuous batching | Общую механику autoregressive generation, prefill/decode and scheduler. |
| 2 | BentoML LLM inference metrics | Нормальные определения TTFT, TPOT, ITL, throughput, goodput and p99. |
| 3 | vLLM docs + PagedAttention paper | Почему KV-cache memory management стал центральной темой serving. |
| 4 | SGLang docs + paper | Почему multi-call/program-like LLM apps требуют cache reuse, routing and structured generation. |
| 5 | TensorRT-LLM/Triton docs | Как выглядит более низкоуровневый NVIDIA production stack и почему он сложнее в эксплуатации. |
| 6 | Habr explainers | Русский слой для интуиции и формулировок, но technical claims сверять с primary docs/papers. |
Что спрашивают на собеседовании
- Почему LLM inference делят на prefill and decode?
- Почему KV-cache одновременно ускоряет генерацию и создает memory bottleneck?
- Что делает PagedAttention и почему это не просто “ускорение attention”?
- Как continuous batching может улучшить throughput, но ухудшить p99 или TTFT?
- Когда выбирать vLLM, когда смотреть SGLang, а когда TensorRT-LLM/Triton?
- Какие метрики ты покажешь перед rollout новой serving config?
Иллюстрация, которую стоит добавить
Материалы
С чего начать
Course backbone for language-model systems: autoregressive generation, resource accounting and inference systems context.
Learner-friendly official explanation of prefill/decode, continuous batching, PagedAttention and serving metrics.
Clear definitions of TTFT, TPOT, ITL, latency, throughput, goodput and p99-oriented monitoring.
Официальные docs
Official source for prefix caching behavior, cache blocks, hashing and constraints in vLLM.
Official docs for SGLang serving, RadixAttention, routing, structured generation and cache reuse.
Advanced official design note on hierarchical KV-cache for long-context and high-throughput serving.
Source of truth for NVIDIA optimized LLM inference stack and TensorRT-LLM deployment concepts.
Official Triton guide for batching, concurrent execution and latency/throughput measurement.
Reference architecture for HF TGI and serving-engine vocabulary; verify current project status before greenfield use.
Production cases
Production case for search-scale multi-model LLM serving; treat reported numbers as source-specific.
Vertical SLM serving case focused on TTFT/TPOT and Triton/TensorRT-LLM deployment.
Vendor case for multi-adapter serving; useful as a lead, not as independent proof for quality or speed claims.
Papers / reports
Canonical paper behind vLLM and PagedAttention; use for KV-cache block/page memory-management claims.
Primary paper for SGLang, RadixAttention and structured language model programs.
Systems paper for iteration-level scheduling and continuous batching in generation serving.
Modern source on chunked prefill and scheduling trade-offs between prefill, decode, latency and throughput.
Reference
Russian explainer for KV-cache, memory growth and autoregressive generation; verify exact claims against primary docs/papers.
Russian explainer for vLLM internals and serving-engine vocabulary; useful for wording, not as sole technical proof.