System Design Space
Граф знанийНастройки

Обновлено: 21 июня 2026 г. в 20:27

Оптимизация инференса больших языковых моделей

сложный

Внутренности LLM-движка инференса: prefill против decode, метрики TTFT/TPOT и goodput, KV-cache и PagedAttention, continuous batching, квантизация (GPTQ/AWQ/FP8), спекулятивное декодирование, параллелизм и экономика стоимости за токен.

Соседняя глава про архитектуру сервинга описывает внешний контур: режимы онлайн/пакет/поток, маршрутизацию, бюджет задержек и автомасштабирование. Эта глава — про внутренности LLM-движка инференса: что происходит внутри одного узла, когда большая языковая модель реально генерирует ответ токен за токеном.

Наивный инференс LLM медленный и дорогой по фундаментальной причине: текст рождается авторегрессионно, и каждый новый токен требует отдельного прохода по всей модели. Ключ к оптимизации — увидеть, что фаза prefill упирается в вычисления и формирует TTFT, а фаза decode упирается в пропускную способность памяти и формирует скорость потока токенов (TPOT).

Дальше разбираем рычаги движка: KV-cache и PagedAttention, continuous batching из Orca, квантизацию весов и KV-cache (GPTQ, AWQ, FP8/INT8), спекулятивное декодирование, параллелизм и prefill-decode disaggregation, а также ёмкость и экономику стоимости за токен под SLO.

Практическая польза главы

Авторегрессия и две фазы

Ответ из сотен токенов — это сотни последовательных проходов по модели. Prefill обрабатывает весь промпт за один проход (compute-bound, задаёт TTFT), а decode генерирует по одному токену, читая на каждом шаге все веса и весь KV-cache (memory-bandwidth-bound, задаёт TPOT/inter-token latency). Разделение этих фаз — основа всех приёмов оптимизации.

KV-cache и PagedAttention

KV-cache хранит ключи и значения внимания, чтобы не пересчитывать его на каждом токене; он линейно растёт с контекстом и пакетом и доминирует в видеопамяти. Наивные движки теряют 60-80% памяти на фрагментацию. Kwon et al. (SOSP 2023) переносят идею страничной памяти ОС в внимание: блоки фиксированного размера на несмежной памяти убирают фрагментацию и дают рост throughput в 2-4x при той же задержке.

Батчинг и квантизация

Continuous (in-flight) батчинг из Orca (OSDI 2022) пересобирает пакет на каждой итерации и держит загрузку GPU высокой. Квантизация снижает память и ускоряет decode: weight-only GPTQ и AWQ сжимают веса до 3-4 бит, FP8/INT8 ускоряет обе фазы, квантизация KV-cache освобождает память под более крупные пакеты и длинные контексты — всё это ценой риска для качества, который нужно мерить на своих данных.

Спекулятивность, параллелизм, экономика

Спекулятивное декодирование (Leviathan et al., ICML 2023; Medusa/EAGLE) рождает несколько токенов за один тяжёлый проход при хорошем согласии draft- и target-модели. Tensor/pipeline/sequence parallelism и prefill-decode disaggregation масштабируют большие модели и разносят фазы по пулам. Итоговая метрика эксплуатации — стоимость за 1000 токенов под раздельные TTFT/TPOT-SLO.

Соседняя глава

Архитектура сервинга и инференса моделей

Там — общий контур сервинга (онлайн/пакет/поток, маршрутизация, автомасштабирование). Здесь — внутренности движка большой языковой модели (LLM).

Читать обзор

Соседняя глава «Архитектура сервинга и инференса моделей» описывает внешний контур: режимы онлайн/пакет/поток, маршрутизацию, бюджет задержек и . Эта глава — про то, что происходит внутри одного узла, когда реально генерирует ответ. Мы не повторяем контур сервинга, а разбираем движок : KV-cache, батчинг, квантизацию, спекулятивное декодирование и параллелизм.

Наивный инференс медленный и дорогой по фундаментальной причине: текст генерируется авторегрессионно — токен за токеном, и каждый новый токен требует отдельного прохода по всей модели. Один ответ из сотен токенов — это сотни последовательных проходов, в каждом из которых GPU читает все веса модели ради нескольких операций на токен. Дальше всё крутится вокруг одного наблюдения: prefill и decode упираются в разные ресурсы, и оптимизировать их одним приёмом не получится.

Две фазы декодирования: prefill и decode

Prefill — обработка промпта

Все токены входного промпта проходят через сеть за один проход и заполняют параллельно. Это фаза с большим числом матричных умножений: она упирается в вычисления (compute-bound) и определяет TTFT.

Decode — генерация по токену

Каждый следующий токен считается отдельным проходом, который читает все накопленные веса и KV-cache. Здесь почти нет арифметики на байт прочитанной памяти, поэтому фаза упирается в (memory-bandwidth-bound) и определяет скорость потока токенов.

Где упирается инференс LLM

Один запрос проходит обе фазы, и каждая упирается в свой ресурс: prefill нагружает вычисления и формирует TTFT, decode читает память на каждый токен и формирует TPOT. Отсюда и расходятся дальнейшие приёмы оптимизации.

Prefillвесь промпт за 1 проходcompute-bound → TTFTDecode (по одному токену)tok 1tok 2tok 3tok 4tok 5Каждый шаг decode читает: веса модели + весь KV-cacheмало арифметики на байт памяти → memory-bandwidth-boundскорость потока токенов определяется TPOT / inter-token latencyУзкое местоprefill: вычисленияdecode: память

Метрики и компромисс задержка ↔ пропускная способность ↔ стоимость

Время до первого токена

TTFT

Time-to-first-token: задержка от прихода запроса до первого сгенерированного токена. Зависит в основном от длины промпта, прогрева и фазы prefill; именно её чувствует пользователь как «модель задумалась».

Задержка между токенами

TPOT / ITL

Time-per-output-token (он же inter-token latency — задержка между токенами): среднее время на каждый следующий токен в фазе decode. Определяет, насколько «плавно» льётся ответ при стриминге; обратная величина — скорость потока для одного запроса.

Пропускная способность

tokens/s

Суммарная скорость генерации токенов по всем запросам на узле. Растёт с размером пакета и высокой , но почти всегда конкурирует с задержкой отдельного запроса.

Полезная пропускная способность

goodput

Доля запросов, обслуженных в рамках по TTFT и TPOT. Высокий tokens/s бесполезен, если половина запросов нарушает SLO по задержке.

Эти метрики тянут в разные стороны: укрупнение пакета поднимает tokens/s и снижает стоимость за токен, но ухудшает TPOT и . Поэтому одну метрику оптимизировать бесполезно — выигрыш нужно мерить по задержке, пропускной способности и стоимости сразу, иначе улучшение по одной оси молча оплачивается другой.

KV-cache: главный потребитель памяти

Что это

KV-cache хранит ключи и значения внимания для всех уже обработанных токенов, чтобы при генерации каждого нового токена не пересчитывать внимание по всей последовательности заново. Без него decode деградировал бы до квадратичной стоимости.

Почему доминирует в памяти

Размер KV-cache линейно растёт с длиной контекста, числом слоёв и запросов в пакете. На длинных контекстах он легко превосходит сами веса модели и становится главным потребителем , ограничивая максимальный размер пакета.

Фрагментация

Наивные движки резервируют непрерывный буфер под максимальную длину каждого запроса. Реальные ответы короче, поэтому возникают внутренняя и внешняя фрагментация и зарезервированная, но неиспользуемая память — до 60–80% по измерениям авторов vLLM.

PagedAttention / vLLM

Kwon et al. (SOSP 2023) переносят идею страничной виртуальной памяти ОС в внимание: KV-cache хранится в небольших блоках фиксированного размера, отображаемых на несмежную физическую память. Это убирает почти всю фрагментацию, позволяет совместно использовать блоки между запросами и поднимает пропускную способность в 2–4 раза при той же задержке.

Батчинг: от статического к continuous

Статический пакет

Запросы собираются в фиксированный пакет и обрабатываются до общего завершения. Короткие ответы простаивают, ожидая самый длинный в пакете, а новые запросы ждут следующего окна — низкая загрузка и высокая хвостовая задержка.

Динамический пакет

Движок ждёт короткое окно и формирует пакет на лету, балансируя задержку и заполнение. Лучше статического, но всё ещё планирует на уровне целого запроса, поэтому «застревает» на самых длинных генерациях. Подробнее про окна — в соседней главе про сервинг.

Continuous / in-flight batching

Orca (OSDI 2022) предлагает планирование на уровне итерации: пакет пересобирается на каждом шаге декодирования. Завершившийся запрос немедленно покидает пакет, а новый занимает его место, не дожидаясь остальных. Selective batching применяет пакетирование только к тем операциям, где это корректно. Так загрузка GPU держится высокой даже при разной длине ответов.

Continuous (in-flight) батчинг — главный приём, поднимающий : пакет не простаивает в ожидании самого длинного ответа, а постоянно «дозаполняется» новыми запросами. Вместе с paged KV-cache это база современных движков (vLLM, TensorRT-LLM).

Квантизация: качество ↔ скорость ↔ память

МетодЧто делаетЭкономия памятиКомпромисс
GPTQ (weight-only)Послойная квантизация весов до 3–4 бит на основе приближённой информации второго порядка≈4× меньше под веса (FP16 → INT4)Почти без потери качества на 4 битах (на 3 битах деградация заметнее и лучше переносится очень крупными моделями); квантизует 175B-модель за ~4 GPU-часа
AWQ (weight-only)4-битная квантизация с защитой ~1% «значимых» каналов по статистике активаций≈4× меньше под весаЛучшая устойчивость качества, чем у наивного round-to-nearest; >3× ускорение vs FP16 в TinyChat
FP8 / INT8Квантизация весов и/или активаций до 8 бит; FP8 нативно ускоряется на современных GPU≈2× меньше под веса; ускоряет и prefill, и decodeМинимальная потеря качества при аккуратной калибровке; требует поддержки железа
Квантизация KV-cacheХранение ключей и значений в INT8/FP8 вместо FP16≈2× меньше под KV-cache → больше пакет / длиннее контекстОсвобождает память под более крупные пакеты; риск деградации на очень длинных контекстах

GPTQ (Frantar et al.) и AWQ (Lin et al.) — это weight-only квантизация: сжимаются только веса, что сильнее всего помогает memory-bandwidth-bound фазе decode. FP8/INT8 сжимают и активации, ускоряя обе фазы на железе с нативной поддержкой. Квантизация KV-cache освобождает память под более крупные пакеты и длинные контексты.

Спекулятивное декодирование

Идея Leviathan, Kalman, Matias (ICML 2023): маленькая быстрая draft-модель «угадывает» сразу несколько следующих токенов, а большая target-модель проверяет их все за один параллельный проход. Принятые токены сохраняются, первый отвергнутый и далее — пересчитываются. Выход математически идентичен обычному декодированию, но несколько токенов рождаются за один тяжёлый проход — авторы показывают ускорение в 2–3 раза на T5-XXL.

Medusa добавляет к модели несколько «голов», предсказывающих будущие токены без отдельной draft-модели; EAGLE предсказывает не токены, а признаки следующего шага, повышая процент принятия. Приём помогает, когда draft хорошо согласуется с target (предсказуемый текст, код); при низком проценте принятия накладные расходы могут свести выигрыш на нет или даже замедлить генерацию.

Параллелизм для больших моделей

Tensor parallelism

Каждый слой (матрицы внимания и MLP) разрезается между GPU, которые синхронно считают свою долю и обмениваются частичными результатами на каждом слое. Снижает задержку и память на GPU, но требует быстрого межсоединения NVLink и чувствителен к его пропускной способности.

Pipeline parallelism

Модель режется по слоям на стадии, разложенные по разным GPU; запросы текут по конвейеру. Дёшево по коммуникации, но создаёт «пузырь» простоя на краях конвейера, который сглаживают микропакетами.

Sequence parallelism

Длинная последовательность и связанный с ней KV-cache распределяются между устройствами вдоль оси токенов. Снимает ограничение памяти на сверхдлинных контекстах, дополняя tensor- и pipeline- .

Prefill–decode disaggregation

Compute-bound фаза prefill и memory-bandwidth-bound фаза decode разносятся на разные пулы GPU. Это убирает взаимные помехи (длинный prefill больше не «душит» поток decode у соседей) и позволяет масштабировать и тюнить фазы независимо.

Ёмкость и эксплуатация

Выбор размера пакета

Больше пакет — выше tokens/s и загрузка GPU, но хуже TPOT и риск нарушить целевой уровень сервиса (SLO). Размер пакета выбирают по кривой goodput: наибольший пакет, при котором TTFT и TPOT ещё укладываются в бюджет.

Автомасштабирование под целевой уровень сервиса (SLO)

ведут не по средней загрузке, а по нарушению TTFT/TPOT-SLO и глубине очереди. Прогрев тяжёлого -движка долгий, поэтому нужна заранее тёплая ёмкость — как описано в соседней главе про контур сервинга.

Экономика стоимости за токен

Главная единица экономики — стоимость за 1000 токенов: цена GPU-часа, делённая на устойчивый tokens/s в рамках SLO. Квантизация, непрерывное пакетирование (continuous batching) и disaggregation снижают её, повышая полезную утилизацию железа.

Ключевые компромиссы

  • Крупный пакет и длинное окно поднимают tokens/s и снижают стоимость за токен, но ухудшают TTFT/TPOT и хвостовую задержку интерактивных запросов.
  • Агрессивная квантизация (особенно ниже 4 бит и квантизация KV-cache на длинных контекстах) экономит память и ускоряет инференс ценой риска для качества — её нужно мерить на своих задачах, а не доверять усреднённым бенчмаркам.
  • Спекулятивное декодирование ускоряет decode при хорошем согласии draft- и target-модели, но при низком проценте принятия добавляет накладные расходы и может замедлить генерацию.
  • Тензорный параллелизм (tensor parallelism) снижает задержку, но требует дорогого быстрого интерконнекта; конвейерный параллелизм (pipeline parallelism) дёшев по связи, но добавляет «пузырь» простоя — выбор зависит от топологии узла.

Частые ошибки

Запускать LLM «как обычную модель» без paged KV-cache и непрерывного пакетирования (continuous batching) и упираться в фрагментацию памяти и низкую загрузку GPU.
Оптимизировать только средний tokens/s, игнорируя goodput: высокая пропускная способность при массовом нарушении TTFT/TPOT целевого уровня сервиса (SLO) бесполезна для продукта.
Включать квантизацию или квантизацию KV-cache без замера качества на собственных данных и длинах контекста.
Смешивать длинный prefill и поток decode на одном пуле без приоритезации или disaggregation, из-за чего тяжёлые промпты «съедают» задержку чужих запросов.

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

Начинайте с современного движка (vLLM, TensorRT-LLM): paged KV-cache и непрерывное пакетирование (continuous batching) дают наибольший прирост при минимальном риске для качества.
Подбирайте размер пакета и конфигурацию по кривой goodput под раздельные TTFT- и TPOT-целевые уровни сервиса (SLO), а не по средней задержке.
Складывайте техники послойно: квантизация весов → квантизация KV-cache → спекулятивное декодирование → параллелизм/disaggregation, проверяя качество на каждом шаге.
Ведите стоимость за 1000 токенов как первоклассную метрику рядом с задержкой и качеством и пересчитывайте её при каждом изменении конфигурации.

Источники и материалы

Карта источников: vLLM/PagedAttention держит объяснение KV-cache и блочной памяти; Orca — continuous batching; GPTQ/AWQ — квантизацию; speculative decoding paper — ускорение через черновую модель; TensorRT-LLM — практические реализации in-flight batching, paged KV-cache и FP8/INT8.

Связанные главы

  • Архитектура сервинга и инференса моделей - Соседняя глава про общий контур сервинга: онлайн/пакет/поток, маршрутизация, бюджет задержек и автомасштабирование, в который встроен движок большой языковой модели (LLM).
  • AI Engineering: обзор - Где оптимизация инференса стоит в жизненном цикле AI-приложения и как связана с оценкой качества и стоимостью.
  • Архитектура системы GenAI с извлечением контекста (RAG) - Как длинные контексты извлечения (RAG) нагружают KV-cache и почему оптимизация инференса определяет задержку и цену ответа.
  • История ускорителей NVIDIA - Почему пропускная способность памяти и поддержка FP8 на ускорителях напрямую определяют пределы инференса большой языковой модели (LLM).

Чтобы отмечать прохождение, включи трекинг в Настройки