ML‑модели применяются в сервисах Яндекса уже много лет, мы накопили большой опыт в их обучении. Статьи об этом коллеги регулярно публикуют, в том числе на Хабре. Но сегодня хочу обсудить другую не менее важную задачу — ускорение инференса (процесса работы на конечном устройстве) моделей. Скорость зависит от разных условий, главным образом от архитектуры и железа, но есть множество интересных способов повлиять на неё. Особенно актуальна проблема тяжёлого инференса при использовании больших языковых моделей (LLM) — на то они и large!

Для команды YandexGPT, в которой я и тружусь вместе со своими коллегами, тема инференса LLM находится в разряде вечных вопросов. С предыдущей статьи прошёл уже почти год, опыта у нас стало больше — получилось протестировать новые подходы, которыми и хочется поделиться сегодня.

Большой плюс — универсальность этих методов. У большинства популярных опенсорсных LLM, доступных энтузиастам, LLaMa‑подобная архитектура, в которой всё это прекрасно применимо. Более того, в популярных фреймворках можно найти похожие решения. Скорее всего, они дадут меньший буст по скорости, чем тот пайплайн, который мы сделали специально для YandexGPT, но результаты в любом случае будут достойные. Ещё одно семейство архитектур LLM, для которого подобные техники актуальны, — MoE (Mixture of Experts). По сути, они базируются на тех же LLaMa‑подобных принципах, и добавление экспертов достраивается как бы поверх привычной архитектуры. Поэтому и для них методы из этой статьи будут работать при условии некоторых доработок и изменений.

Прежде чем перейти к новому, давайте коротко напомню, какие методы ускорения инференса рассматривались в прошлой статье:

  • Дистилляция подойдёт тем, кто готов использовать две модели: большую и маленькую. В прошлой статье описано несколько полезных трюков, которые помогут извлечь из этого подхода максимум.

  • Квантизация поможет сократить объёмы потребляемых вычислительных ресурсов и одновременно повысить скорость инференса. Для квантизации весов можно использовать популярный метод GPT‑Q, а если хотите квантизировать и веса, и активации, можно обратиться к SmoothQuant.

  • Есть и другие подходы к ускорению, например Speculative Decoding и Continuous Batching.

Кстати, перечисленные методы можно и нужно комбинировать, чтобы добиться наилучшего ускорения. В этом материале каждая из тем получает развитие: нас ждёт ещё больше методов дистилляции, подходов к квантизации и спекулятивному декодированию. Поехали!

Дистилляция знаний: Hard-label, Soft-label и On-policy

Дистилляция знаний — мощный метод создания небольших эффективных языковых моделей с сохранением бóльшей части возможностей LLM. Первоначально предложенный Хинтоном и соавторами в 2015 году, этот подход предполагает обучение меньшей модели‑ученика, чтобы имитировать поведение более крупной и мощной модели‑учителя. Поскольку размеры современных LLM только растут, часто достигая сотен миллиардов или даже триллионов параметров, дистилляция — вещь очень полезная.

Ключевые преимущества:

  • Модели меньшего размера требуют гораздо меньше вычислительных ресурсов, что ускоряет их инференс и позволяет хорошо экономить.

  • Дистилляция делает LLM пригодными для развёртывания на периферийных устройствах и в средах с ограниченными ресурсами.

  • Также дистиллированные модели нередко превосходят модели аналогичного размера, обученные на исходном наборе данных за счет усовершенствованных знаний и способности к обобщению, присущей модели‑учителю.

LLM обладают знаниями, выходящими за рамки простого получения корректных ответов: они кодируют обширные внутренние представления и распределения вероятностей. Это «тёмное знание», по определению Хинтона, даёт ценную информацию о том, как разные результаты связаны друг с другом. При дистилляции такое знание может быть перенесено в модель‑ученика. Например, учитель присваивает сходные вероятности семантически связанным словам, даже если только одно из них является правильным в заданном контексте, а модель‑ученик улавливает эти нюансы и работает надёжнее.

Hard-label дистилляция

Hard‑label дистилляция — наиболее простой подход к передаче знаний от учителя к ученику. Сначала большая модель используется для генерации датасета, состоящего из пар вход‑выход. Затем модель‑ученик обучается на этом наборе данных в парадигме supervised learning.

Процесс обычно начинается со сбора большого набора промптов \{x_n\}_{n=1}^N, полученных из уже существующих датасетов или специально синтезированных. Затем учитель p(y \mid x) обрабатывает промпты и выдаёт ответы y_n, в результате чего мы получаем синтетический датасет из размеченных примеров \mathcal{D} = \{x_n, y_n\}. Этот подход особенно удобен, когда качественных данных для обучения не хватает — модель‑учитель может сгенерировать множество таких примеров, отражающих усвоенные знания. Маленькая модель учится точно имитировать ответы, сгенерированные учителем, рассматривая их как ground truth:

L(\theta) := \frac{1}{N} \sum_{n=1}^N \sum_{t=1}^{T_n} \log q_\theta(y_{nt} \mid x_n, y_{n, 1}, \dots, y_{n, t-1}), \quad y_n \sim p(y \mid x_n)

Эта формула работает для последовательностей и текстов. Больше о плюсах, минусах и нюансах этого подхода можно узнать в предыдущей статье об ускорении LLM.

Soft-label дистилляция

Soft‑label дистилляция предоставляет ученику полный доступ к внутренним распределениям вероятностей модели‑учителя, а не только к конечному результату. Вместо того, чтобы использовать на каждом шаге hard‑метки, дистиллированная модель обучается так, чтобы соответствовать полному распределению вероятностей учителя по словарю \mathcal{V} (т. н. мягкие метки). Такой подход обеспечивает более чистый обучающий сигнал, поскольку он учитывает не только токены, предсказанные большой моделью, но и то, насколько она уверена в каждом возможном результате.

Soft‑label дистилляция эффективно отражает неопределённость модели учителя, когда та присваивает сходные вероятности нескольким правдоподобным токенам. Например, при прогнозировании следующего слова во фразе «Кошка села на ___» LLM может присвоить 0,4 вероятности слову «коврик», 0,35 — слову «подстилку» и меньшие вероятности другим вариантам. Обучение с использованием мягких вероятностных ориентиров позволяет ученику усваивать более тонкие взаимосвязи между маркерами по сравнению с hard‑метками, которые просто присваивали бы слову «коврик» полную вероятность каждый раз.

Схема SLIM-дистилляции. Источник
Схема SLIM-дистилляции. Источник

Для повышения эффективности обучения методы наподобие SLIM часто используют уменьшенное подмножество распределения вероятностей модели учителя. Например, они могут учитывать только верхние 5% вероятностей для каждой выборки, что в 20 раз сокращает объём требуемой памяти.

Soft‑label подход, как правило, даёт лучшую производительность модели‑ученика и при этом требует меньше данных для обучения, чем Hard‑label. Рост эффективности обусловлен более насыщенными обучающими сигналами в каждом примере. Более того, мягкие метки действуют как естественная форма регуляризации, предотвращая чрезмерную уверенность ученика в своих прогнозах. Функция потерь для Soft‑label дистилляции обычно включает в себя минимизацию показателя несоответствия (такого как KL‑дивергенция) между распределениями вероятностей ученика и учителя:

L(\theta):= \frac{1}{N} \sum_{n=1}^N \sum_{t=1}^{T_n} D_{KL}\left(p(y_{nt} \mid x_n, y_{n, 1:t-1}) \mid\mid q_\theta(y_{nt} \mid x_n, y_{n, 1:t-1})\right) = = \frac{1}{N} \sum_{n=1}^N \sum_{t=1}^{T_n} \sum_{v \in \mathcal{V}} p(y_{nt} = v \mid x_n, y_{n, 1:t-1}) \log \frac{p(y_{nt} = v \mid x_n, y_{n, 1:t-1})}{q_\theta(y_{nt} = v \mid x_n, y_{n, 1:t-1})}

Однако Soft‑label дистилляция требует больших вычислительных ресурсов во время обучения, поскольку нам важно сохранять и обрабатывать полные распределения вероятностей, а не отдельные индексы токенов. Также требуется более глубокая интеграция ученика с учителем для доступа к внутренним вероятностям большой модели, что осложняет реализацию по сравнению со стандартными подходами. Из‑за этого подход несовместим с большинством моделей, использующих только API как модель‑учителя.

Наконец, и Soft‑, и Hard‑label дистилляция страдают от предвзятости: модель‑ученик обучается на примерах, навязанных учителем, но впоследствии должна самостоятельно генерировать ответы. Это несоответствие между условиями обучения и инференса может привести к накоплению неточностей в ответах (т. н. exposure bias), поскольку дистиллированная модель не учится исправлять собственные ошибки.

On-policy дистилляция и смягчение exposure bias

Итак, существенной проблемой в традиционных подходах к дистилляции является проблема exposure bias, из‑за которой качество модели‑ученика ухудшается вследствие того, что она обучалась на примерах, полученных большой моделью, а не на собственных генерациях.

On‑policy дистилляция решает эту проблему, включая в обучение собственные генерации модели‑ученика. Вместо того, чтобы учиться исключительно на основе выходных данных учителя, ученик генерирует свои результаты, которые затем оцениваются учителем. Так получается цикл обратной связи, в котором ученик совершенствует свои стратегии генерации, а не просто имитирует результаты большой модели. Это похоже на реальный образовательный процесс, в котором хороший преподаватель не даёт верные ответы, а указывает на ошибки, позволяя студенту самостоятельно найти решение.

Типичный процесс обучения выглядит так:

  1. Ученик генерирует последовательность на основе промпта.

  2. Учитель оценивает ответ ученика и выдаёт обратную связь на уровне токенов.

  3. Ученик обновляется, чтобы максимизировать оценки преподавателя при сохранении разнообразия генераций.

Как правило, расхождения определяются на уровне предложений, а не токенов. В частности, прямая KL‑дивергенция D_{KL}(q_\theta \mid\mid p) — хороший вариант. Она отлично работает благодаря наличию свойства вырождения в моду распределения: если ученик не может полностью охватить распределение учителя, он сосредотачивается на той части вероятностей, которую может «переварить», вместо того, чтобы пытаться охватить как можно больше (как происходит в случае с обратной KL‑дивергенцией D_{RKL}(p \mid\mid q_\theta), при этом не достигая лучшего качества. Вот что мы хотим оптимизировать:

L(\theta)=D_{KL}(q_\theta \mid\mid p)==\frac{1}{N} \sum_{n=1}^N \mathop{\mathbb{E}}_{q_\theta(y_n \mid x_n)} \sum_{t=1}^{T_n} \sum_{v} q_\theta(y_{n,t}=v \mid x_n, y_{n,1:t-1}) \log \frac{q_\theta(y_{n,t}=v \mid x_n, y_{n,1:t-1})}{p(y_{n,t}=v \mid x_n, y_{n,1:t-1})}

Однако оптимизация лосса представляет большую трудность, поскольку нам нужно дифференцировать математическое ожидание \mathbb{E} для всех значений y_n для каждого промпта x_n, что невозможно комбинаторно даже для одного запроса, не говоря уже о большом датасете. Исследователи решают эту задачу, используя различные приёмы и техники (подробнее я описал во всё той же прошлогодней статье об ускорении инференса).

Более практичный подход заключается в сэмплировании ответов из модели‑ученика q_\theta(y \mid x) и оценке их с использованием учителя p(y \mid x) без обратного распространения результатов в процессе сэмплинга. Хотя это немного ограничивает способность ученика к планированию, он всё ещё может учиться на собственных ошибках с помощью сигналов дистилляции на уровне токенов.

Концепция получила дальнейшее развитие в недавнем исследовании по спекулятивной дистилляции знаний. Она имитирует интуитивное взаимодействие учителя и ученика: по мере того, как ученик последовательно генерирует токены, учитель активно отслеживает и сразу же исправляет ошибки. Такой механизм вмешательства гарантирует, что результаты обучения дистиллированной модели будут соответствовать опыту учителя, и обеспечивает более стабильное качество обучения.

Схема SKD. Источник
Схема SKD. Источник

Функция потерь при этом выглядит так же, как при Soft‑label дистилляции:

L(\theta):= \frac{1}{N} \sum_{n=1}^N \sum_{t=1}^{T_n} D\left(p(y_{nt} \mid x_n, y_{n, 1:t-1}) \mid\mid q_\theta(y_{nt} \mid x_n, y_{n, 1:t-1})\right)

Разница заключается в том, как получаются обучающие выборки y_{n}. Каждый следующий токен сэмплируется из распределения ученика q_\theta(y_{n,t} \mid x_n, y_{n,1:t-1}), но при этом на каждом шаге мы проверяем, является ли выбранный токен высоковероятным для распределения учителя, сравнивая y_{n,t} и топ-k наиболее вероятных токенов из распределения учителя p(y_{n,t} \mid x_n, y_{n,1:t-1}).

Квантизация — в погоне за качеством 

В предыдущей серии мы обсуждали, что квантизацию трансформеров впервые применили к BERT‑like моделям. Тогда квантовали только веса, и всё работало. Но когда дело дошло до активаций, возникли проблемы выбросов. В тензоре активаций стали появляться значения, сильно выпадающие из распределения (выбросы). При калибровке они учитывались в статистике, из‑за чего scale с zero point подбирались некорректно.

Мы рассматривали три метода, которые с этим борются: LLM.int8(), SmoothQuant и GPT‑Q. Но к проблеме выбросов в активациях можно подойти ещё и с другой стороны.

FP8

Во всех рассмотренных ранее методах квантизация перегоняла вещественные числа (FP16/BF16) в целочисленный формат (INT8). Такой формат выбран неслучайно. На поколении видеокарт NVIDIA, начиная с Turing/Ampere, появилась возможность выполнять матричные перемножения в INT8 в два раза быстрее по сравнению с FP16. Именно такая особенность устройства побудила всех использовать именно INT8-квантизацию. Но что если формат на самом деле неоптимален?

В качестве напоминания рассмотрим общий принцип форматов чисел с плавающей точкой. В них часть битов отводится на экспоненту (exponent на картинке), а часть — под мантиссу (fraction на картинке) и один на знак.

Общая схема форматов чисел с плавающей точкой. Источник
Общая схема форматов чисел с плавающей точкой. Источник

Из такого формата несложно получить десятичное представление для числа (справа от знака равенства) по формуле ниже:

\left(\sum_{n=0}^{p-1} \mathrm{bit}_{n}×2^{-n} \right)×2^{e}

На самом деле помимо INT8 существуют и другие 8-битные форматы, которые обобщённо называются FP8:

  1. E4M3: 4 бита отводится на экспоненту, 3 на мантиссу, 1 на знак.

  2. E3M4: 3 бита отводится на экспоненту, 4 на мантиссу, 1 на знак.

  3. E5M2: 5 бита отводится на экспоненту, 2 на мантиссу, 1 на знак.

Сравнение квантизованных значений и ошибки квантизации для разных форматов представления чисел. Источник
Сравнение квантизованных значений и ошибки квантизации для разных форматов представления чисел. Источник

В статье авторы исследуют вопрос квантизации тензора со значениями из нормального распределения, но с добавлением небольшой доли выбросов — как раз похожую картину мы обычно наблюдаем в активациях (см. левый рисунок).

Оказалось, что квантизация значений из такого распределения в разные типы значительно отличается (см. рисунок посередине). В INT8-квантизации центральный регион покрыт квантизованными значениями гораздо более разреженно, чем в FP8, так как все значения посередине расположены всегда на расстоянии step‑size, а он сильно меняется при добавлении выбросов.

Такая особенность сказывается и на общей ошибке квантизации (см. правый рисунок), где форматы E4M3/E3M4 показывают себя значительно лучше INT8. E5M2 продемонстрировал наибольшую из всех ошибок, потому что включает в себя всего лишь 2 бита мантиссы. Поэтому такой формат применим скорее для распределений с большей дисперсией.

В контексте применения FP8-квантизации к LLM можно и нужно описывать итоговые потери качества и ускорения. Оказалось, что абсолютно все вариации E4M3 (static/dynamic, per‑token/per‑tensor) дают lossless‑результаты по качеству в среднем на более чем 30 few‑shot бенчмарках (см. таблицу ниже). Поэтому для применения в реальных задачах нужно брать самую эффективную по скорости реализацию, а это вариант per‑tensor/static.

Сравнение качества различных методов квантизации с FP16 (в процентных пунктах)
Сравнение качества различных методов квантизации с FP16 (в процентных пунктах)

В итоге такой подход даёт ускорение около ×1,4 в реальных генеративных сценариях по сравнению с 16-битным инференсом.

SpinQuant

Помимо 8-битных матричных перемножений на части современных видеокарт доступны и INT4-перемножения c итоговым ускорением в 4 раза по сравнению с FP16. К сожалению, в самых последних поколениях Hopper и Blackwell такие матричные перемножения недоступны, но зато они есть в более ранних Ampere и Ada Lovelace.

Поэтому W4A4-квантизация вполне может пригодиться для реальных применений в продакшене при условии приемлемых потерь качества, в чём и разбирались авторы статьи SpinQuant. Ключевая идея статьи — научиться бороться с выбросами в активациях ещё лучше, чем SmoothQuant. Для этого авторы всё так же используют механизм балансировки сложности квантизации между весами и активациями с помощью домножения их на матрицу и её обратную. Но, в отличие от SmoothQuant, они используют Rotation Matrices.

На иллюстрации ниже наглядно показано, что количество выбросов при использовании таких вращений сводится к нулю по всем слоям (иллюстрация ниже, схема a), ошибка квантизации в 4 бита слоёв и активаций уменьшается в 2–4 раза по сравнению с исходной моделью и становится стабильной по всем слоям. Визуально подтверждается (см. иллюстрацию ниже), что выбросы действительно сглаживаются как в MHSA (Multi‑head Self‑attention), так и в FFN (Feed Forward Network).

Количество выбросов до/после применения операций вращения. Источник
Количество выбросов до/после применения операций вращения. Источник

Подробнее о Rotation Matrices можно почитать в статье, её статье‑конкуренте QuaRot и их предшественниках. Отдельно хочется подчеркнуть, что в SpinQuant для квантизации всех линейный слоёв, кроме down_proj, в FFN и KV‑cache используются обучаемые матрицы вращений, которые мержатся с весами линейных слоёв и не добавляют никакого оверхеда на инференсе. Это является научной новизной, потому что ранее в таких случаях использовались менее стабильные случайные Адамаровы матрицы, приводившие к значительно большей потере качества (см. иллюстрацию ниже).

Сравнение по zero-shot accuracy для методов вращения. Источник
Сравнение по zero-shot accuracy для методов вращения. Источник

Для квантизации down_proj в FFN и KV‑cache безальтернативно используются случайные Адамаровы матрицы, потому что они позволяют сделать online‑вращение, т. к. вращения в этих местах невозможно смержить с какими‑либо соседними операциями.

Общая диаграмма для интеграции операций вращения в слой трансформера. Источник
Общая диаграмма для интеграции операций вращения в слой трансформера. Источник

Предложенная реализация W4A4KV4-квантизации показывает SOTA‑результаты на бенчмарках качества (см. ниже) и даёт ускорение ×2,7 на этапе генерации.

Прочие методы и техники ускорения

Speculative Decoding

Один из нашумевших методов спекулятивного декодирования — EAGLE. Он отличается от привычной схемы, описанной в первой части статьи, сразу в нескольких аспектах.

Во‑первых, мы передаём скрытые состояния последнего слоя исходной модели в draft‑голову и обучаем её их же предсказывать на выход. Это позволяет итоговой модели использовать больше информации для «угадывания» будущих токенов и в результате даёт больший Acceptance Rate.

Во‑вторых, вместо создания цепочки будущих токенов модель создаёт дерево драфтовых токенов, в процессе проверки которых выбирается наиболее перспективный путь в этом дереве.

Архитектура модели с использованием EAGLE. Источник
Архитектура модели с использованием EAGLE. Источник
Работа механизма дерева драфтовых токенов. Источник
Работа механизма дерева драфтовых токенов. Источник

Всё это способствует общему ускорению процесса по нескольким причинам. Доступ к скрытым состояниям позволяет уменьшить размер драфтовой модели без потерь в Acceptance Rate. Например, использовать только один трансформерный слой (совпадающий по размеру со слоем базовой модели), что сильно уменьшает overhead на стадию drafting‑а и позволяет добиться значительно большего ускорения во всех сценариях. Древовидные драфты значительно увеличивают среднее количество принятых токенов, поскольку по факту дают возможность верифицировать сразу несколько цепочек, причём делать это эффективно и почти настолько же быстро, как с одной цепочкой.

EAGLE может быть в два раза эффективнее с точки зрения соотношения принятых и отвергнутых токенов, чем традиционные методы спекулятивного декодирования, и давать в два раза большее ускорение по сравнению с обычной авторегрессионной генерацией в compute bound сценариях.

KV-cache

В качестве быстрого напоминания о том, что такое KV‑cache, рекомендую прочитать следующий пост. Стоит отметить, что размер KV‑cache растёт линейно с увеличением:

  • длины последовательностей (seqlen);

  • количества слоёв и hidden_size;

  • batch_size.

Поэтому в задачах с длинным контекстом (Long Context) вроде работы с кодом, Chain of Thought и мультимодальных применений (видео, звук) размер KV‑cache начинает быть доминирующим элементом потребления VRAM. Это отражается на размере batch_size, который способно использовать генеративное API, и, как следствие, пропускной способности этого генеративного сценария (output tokens throughput). Помимо этого, KV‑cache необходимо, как и веса модели, грузить на каждом шаге генерации из памяти, поэтому его оптимизация поможет избегать bottleneck‑а при трансфере из VRAM в более низкоуровневые виды памяти GPU.

Как уже было написано выше, техники квантизации успешно применяют не только к весам и активациям, но и к KV‑cache. Это позволяет линейно сжать его в два раза для 8-битной квантизации и в четыре — для 4-битной по сравнению с FP16, что положительно влияет на метрики потребляемого VRAM, latency, RPS и throughput.

KV-cache reuse

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

  • Q&A по юридическим документам;

  • работа с большими данными, например с табличками Excel;

  • multi‑turn диалоги;

  • и другое…

В таких сценариях применима оптимизация KV‑cache reuse, при которой подсчитанный кеш для конкретного префикса сохраняется в VRAM/RAM и может быть переиспользован в другом запросе (возможно с частично совпадающим префиксом) при необходимости. Такой подход способен в разы сократить задержку до первого токена (FTT), стоимость генерации для system prompt и часто применяется на практике.

Для эффективной реализации этого алгоритма необходим PagedAttention, который управляет памятью схожим образом с тем, как это делает операционная система:

  • Когда сохраняются новые записи в кеше, в свою очередь PagedAttention сохраняет их в виде физических non‑contiguous блоков.

  • А dynamic mapping table показывает виртуальный вид кеша как contiguous tensor (см. иллюстрацию).

Алторитм PagedAttention. Источник
Алторитм PagedAttention. Источник

KV-cache compression

Помимо квантизации есть и другие техники сжатия KV‑cache. Один из самых современных — Dynamic Memory Compression. Его идея заключается в том, что далеко не все токены существенны для понимания и продолжения текста, поэтому их можно не сохранять в KV‑cache, а аккумулировать сильно дешевле.

В каждом слое MHSA для каждой временной позиции t появляется предиктор \alpha_{t}, который отвечает за решение: добавлять ли подсчитанные k_{t}, v_{t} в KV‑cache или стоит их саккумулировать в последнюю на данный момент запись в KV‑cache.

Пример того, как расширяется KV-cache в DMC во время инференса
Пример того, как расширяется KV-cache в DMC во время инференса

Такой предиктор \alpha_{t} принимает на вход k_{t} и учится специальным образом в режиме пост‑претрейнa для оригинальной LLM, о чём подробнее можно прочитать в статье. Аккумуляция устроена как простое weighted average между последней записью в KV‑cache и рассчитанными k_{t}, v_{t}, где вес w_{t} тоже получается через предиктор, но принимающий на вход уже q_{t}. Количество таких аккумуляций и определяет степень сжатия KV‑cache и обозначается авторами как CR. С помощью специального дообучения можно добиться произвольного сжатия CR для фиксированной модели. DMC отлично себя показывает на всех CR = 2, 4, 6, 8 по сравнению с другими подходами и позволяет добиться lossless‑сжатия на CR = 2, 4.

Замеры throughput показывают ускорение, соразмерное сжатию, поскольку всегда появляется возможность за счёт освободившейся VRAM увеличить batch_size пропорционально: ×2 для DMC 2× и ×3,5 для DMC 4×.

Сравнение throughput для различных моделей и GPU. Источник
Сравнение throughput для различных моделей и GPU. Источник

Отдельно отмечается, что при максимально влезающем batch_size в конфиге DMC 4× ещё и немного увеличивается latency.

Latency для генерации одного токена. Источник
Latency для генерации одного токена. Источник

Апгрейдим Continuous Batching  

Continuous Batching позволяет вести обработку потока запросов в реальном времени без ожидания формирования полных батчей. В дополнение к нему рекомендуется использовать ещё и ragged tensors. Это ещё один отличный метод повышения утилизации GPU во время инференса. Такие тензоры эффективно представляют последовательности различной длины без необходимости добавления паддингов. Это позволяет использовать на входе предложения или абзацы разной длины — очень распространённый кейс в задачах обработки естественного языка. Такой подход позволяет моделям обрабатывать каждую последовательность в естественном виде и тем самым не расходовать вычислительные ресурсы на бесполезные паддинг‑токены.

Ragged tensors обычно хранятся с использованием комбинации flattened array значений и вспомогательных структур данных, которые определяют границы каждой последовательности. Эта особенность позволяет эффективно индексировать и извлекать отдельные последовательности в тензоре. Сохраняя компактное представление, тензоры оптимально используют память и вычислители, что приводит к дополнительному ускорению инференса.

Ускорение при использовании ragged-тензоров. Источник
Ускорение при использовании ragged-тензоров. Источник

На иллюстрации выше видно, как интеграция ragged‑тензоров в инференс способствует заметному росту производительности и позволяет ускорить выполнение общих задач, связанных с multi‑turn диалогами, примерно на 10%.

Заключение

Итак, если посмотреть на все доступные методы ускорения инференса LLM, описанные в обеих частях нашего мини‑сериала, можно выстроить примерно такую схему:

  • Для улучшения маленьких моделей переносим знания из LLM с помощью дистилляции.

  • Квантизация поможет ускорить модель и сэкономить вычислительные ресурсы. Для lossless‑случая стоит использовать FP8/SmoothQuant в зависимости от новизны ваших GPU. А для агрессивного сжатия лучше всего подойдёт SpinQuant.

  • Среди техник Speculative Decoding лучше всего выбрать EAGLE, потому что она способна принести ускорение на compute bound сценариях.

  • Для ускорения сценариев с длинными контекстами стоит прибегнуть к техникам оптимизации работы KV‑cache: reuse, квантизации и DMC.

  • Для улучшения механизмов батчинга не забудьте сэкономить на удалении паддингов и использовать ragged tensors, а также continuous batching.

  • И наконец, самое главное: все эти техники можно и нужно комбинировать, чтобы получить мультипликативное ускорение как в примере ниже:

Качество VS ускорение инференса при комбинировании методов из статьи
Качество VS ускорение инференса при комбинировании методов из статьи

Надеюсь, статья оказалась для вас полезной! Спасибо, что дочитали — если у вас остались вопросы, не стесняйтесь задавать их в комментариях. Я здесь, чтобы помочь!

Комментарии (0)