Почему генерация токенов — узкое место инференса
Автодополнение в больших языковых моделях работает последовательно: каждый новый токен зависит от всех предыдущих. На этапе декодирования модель обрабатывает по одному токену за шаг, и вычислительная мощность GPU используется лишь на малую долю — основная задержка уходит на чтение весов из памяти, а не на арифметику. Это делает генерацию memory-bound задачей.
Квантование снижает объём весов и ускоряет чтение, но не меняет саму последовательную природу декодирования. Увеличение батча помогает утилизации, но растёт задержка для отдельного запроса. Speculative decoding предлагает другой подход: выполнять несколько шагов декодирования за один проход через целевую модель.
Основная идея: черновик и верификация
Метод строится на наблюдении: распределение следующего токена у большой модели часто совпадает с распределением у маленькой, быстрой модели. Если это так, можно «угадать» несколько токенов вперёд дешёвой моделью и затем проверить их за один проход через целевую.
Алгоритм на каждом шаге:
- Черновая модель (draft model) генерирует K токенов автодополнением. Это маленькая модель с тем же токенизатором, работающая значительно быстрее целевой.
- Целевая модель (target model) выполняет один прямой проход по всем K черновым токенам параллельно — как если бы это был промпт.
- Верификация: для каждой позиции сравнивается распределение вероятностей целевой модели с распределением черновой. Токены принимаются или отклоняются по правилу, которое гарантирует, что итоговое распределение в точности совпадает с распределением целевой модели при обычном автодополнении.
- Принятые токены добавляются в вывод. На первой позиции, где токен отклонён, целевая модель сэмплирует корректный токен из скорректированного распределения.
Ключевое свойство: результат статистически идентичен обычной генерации целевой модели. Качество не теряется — ускоряется только процесс.
Математика верификации
Пусть
p(x) — распределение целевой модели, q(x) — распределение черновой. Для каждого кандидата-токена x_i вычисляется отношение p(x_i) / q(x_i).- Если
p(x_i) >= q(x_i), токен принимается с вероятностью 1.
- Если
p(x_i) < q(x_i), токен принимается с вероятностьюp(x_i) / q(x_i). В случае отклонения сэмплируется из скорректированного распределенияnorm(max(0, p(x) - q(x))).
Это правило из работы Leviathan et al. (2023) и независимо Chen et al. (2023) гарантирует, что итоговое распределение каждого принятого токена в точности равно
p(x).От чего зависит ускорение
Ускорение определяется двумя факторами:
| Фактор | Влияние |
|---|---|
| Acceptance rate (доля принятых токенов) | Чем выше совпадение распределений черновой и целевой модели, тем больше токенов принимается за один проход |
| Стоимость черновой генерации | Если черновая модель слишком медленная или большая, выигрыш от параллельной верификации снижается |
На практике при хорошем совпадении распределений и K = 4–8 черновых токенов ускорение составляет 2–3× по сравнению с обычным автодополнением. При плохом совпадении (например, черновая модель из другого семейства) выигрыш может быть минимальным или даже отрицательным из-за накладных расходов.
Методы без отдельной черновой модели
Не всегда удобно держать вторую модель в памяти. Существуют подходы, которые строят черновые токены без отдельной draft-модели:
N-gram (prompt lookup)
Черновые токены извлекаются из самого промпта или уже сгенерированного текста путём поиска совпадающих n-грамм. Если в контексте встречается последовательность, начинающаяся с последнего токена, она предлагается как черновик. Метод особенно эффективен для задач с высокой повторяемостью: суммаризация, перевод, заполнение шаблонов, код с повторяющимися конструкциями.
Self-speculative decoding
Целевая модель сама генерирует черновик, пропуская часть слоёв или используя ранний выход (early exit). Это экономит память — не нужна вторая модель, но требует модификации архитектуры или поддержки со стороны фреймворка.
EAGLE
Метод, при котором черновые токены предсказываются на основе скрытых состояний целевой модели с помощью лёгкой головы. Это позволяет достичь высокого acceptance rate без полной отдельной модели. Поддерживается в vLLM как один из встроенных методов.
DFlash
Ещё один метод, доступный в vLLM, ориентированный на быстрое формирование черновых последовательностей с минимальными накладными расходами.
Реализация в vLLM
vLLM поддерживает speculative decoding как встроенную функцию. Среди доступных методов:
- n-gram — поиск совпадений в контексте, не требует дополнительной модели.
- suffix — вариация на основе суффиксных совпадений.
- EAGLE — черновик на основе скрытых состояний целевой модели.
- DFlash — быстрый метод формирования черновых последовательностей.
Для использования отдельной черновой модели достаточно указать её при запуске сервера. Пример конфигурации с draft-моделью:
Bash:
vllm serve meta-llama/Llama-3.1-70B-Instruct \
--speculative-model meta-llama/Llama-3.1-8B-Instruct \
--num-speculative-tokens 5
Здесь
--speculative-model задаёт черновую модель, а --num-speculative-tokens — длину черновой последовательности (K). Для n-gram метода вместо --speculative-model используется --speculative-model [ngram] с указанием размера n-граммы.При выборе черновой модели важно:
- Использовать модель из того же семейства и с тем же токенизатором.
- Убедиться, что черновая модель значительно меньше целевой (обычно в 5–10 раз по параметрам).
- Подобрать
num-speculative-tokensэкспериментально: слишком большое K увеличивает стоимость верификации без пропорционального роста принятых токенов.
Ограничения и типичные ошибки
Несовместимый токенизатор. Если черновая и целевая модели используют разные токенизаторы, верификация невозможна — распределения определены над разными пространствами токенов.
Слишком большая черновая модель. Если draft-модель сама по себе медленная, время на генерацию K токенов съедает выигрыш от параллельной верификации. Правило: черновая модель должна быть на порядок быстрее целевой.
Низкий acceptance rate. Если задача сильно отличается от того, на чём черновая модель обучалась, доля принятых токенов падает. В худшем случае каждый шаг верификации принимает 0–1 токен, и накладные расходы делают метод медленнее обычного декодирования.
Влияние на батчинг. При обслуживании множества одновременных запросов speculative decoding усложняет планирование: разные запросы могут принимать разное число токенов, что создаёт неравномерность. Современные движки вроде vLLM с continuous batching справляются с этим, но пиковая пропускная способность может быть ниже, чем при обычном декодировании с большим батчем.
Неприменимость к некоторым задачам. Для задач с высокой энтропией вывода (креативная генерация с высокой температурой, рассуждения с множеством равновероятных путей) acceptance rate снижается, и ускорение становится незначительным.
Когда метод наиболее эффективен
- Низкая температура сэмплирования или greedy-декодирование — распределение более пиковое, совпадение с черновой моделью выше.
- Задачи с предсказуемым продолжением: код, шаблоны, перевод, суммаризация.
- Сценарии с низкой задержкой на запрос (чат-боты, интерактивные ассистенты), где важно время до последнего токена, а не общая пропускная способность.
- Ситуации, когда GPU недогружен из-за малого батча и есть свободная вычислительная мощность для верификации.
Проверка результата
После включения speculative decoding стоит убедиться, что метод действительно даёт выигрыш:
- Сравните время генерации одного и того же промпта с включённым и выключенным speculative decoding.
- Проверьте метрики: vLLM логирует количество принятых токенов на шаг. Если средний показатель ниже 2, метод неэффективен для данной пары моделей и задачи.
- Убедитесь, что вывод статистически не отличается: при одинаковом seed и greedy-декодировании результат должен быть идентичен.
- Нагрузочное тестирование с реальным распределением запросов покажет, не деградирует ли пропускная способность при высоком параллелизме.
Speculative decoding — один из немногих методов ускорения инференса, который не требует компромисса между скоростью и качеством. При правильном подборе черновой модели и параметров он даёт кратное снижение задержки без изменения выходного распределения.
