Главная / Статьи / Спекулятивная декодировка и преждевременный выход: ускорение авторегрессивной декодировки

Спекулятивная декодировка и преждевременный выход: ускорение авторегрессивной декодировки

Подготовка проекта с последующей проверкой, а также использование выходов на уровне уверенности сокращают задержку декодирования, когда позволяют лимиты на приемлемость и точность.

2856 слов

Почему оптимизация декодирования находится на критическом пути

Процесс интерпретации LLM включает этап предзаполнения, который выполняется параллельно для всего входного запроса, и этап декодирования, при котором токены генерируются последовательно. Этап предзаполнения может перегрузить GPU; декодирование же обычно не может этого сделать, поскольку каждый новый токен зависит от предыдущего. Именно эта последовательная зависимость делает задержку в интерактивном режиме высокой, даже если с точки зрения расчётов количество операций FLOPs кажется достаточным.

Prefill phase:
  Input: [token_1, token_2, ..., token_512]  → all 512 tokens processed in parallel
  Matrix shape: [batch, 512, 4096]
  GPU utilization: high — large matrix, full Tensor Core throughput

Decode phase (one step):
  Input: [token_513]  → one token processed
  Matrix shape: [batch, 1, 4096]
  GPU utilization: low - tiny matrix, most CUDA cores idle

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

На каждом шаге декодирования модель формирует запросы к постепенно растущей кэш-структуре ключей/значений. Объём работы на каждом шаге увеличивается с удлинением контекста, в то время как возможности группировки операций ограничиваются требованиями к задержкам в чат-функциях.

One attention head, decode step:

Query Q: [8, 1, 128]   →  8 × 128 = 1,024 elements
Keys  K: [8, 2048, 128] →  8 × 2048 × 128 = 2M elements
Values V: [8, 2048, 128] →  same

Matrix multiply (QKᵀ) per head:
  Shape: [8, 1, 128] × [8, 128, 2048] → [8, 1, 2048]
  FLOPs: 8 × 1 × 128 × 2048 ≈ 2.1M FLOPs per head

For 32 heads: ≈ 67M FLOPs per layer
For 32 layers: ≈ 2.1B FLOPs total per decode step

A100 peak at BF16: ~312 TFLOPS = 312 × 10¹² FLOPs/sec

Time to execute 2.1B FLOPs at 100% utilization:
  2.1 × 10⁹ / 312 × 10¹² ≈ 0.0067 ms

Actual observed decode latency per step: ~10–30ms

Effective compute utilization: < 0.1%

Спекулятивное декодирование: первоначальный вариант, затем проверка

Модель более мелкого масштаба предлагает несколько будущих токенов; целевая модель проверяет их в ходе одного параллельного прямого прохода, принимая префикс и пересобирая данные при первом отклонении. Принятые варианты увеличивают количество эффективных токенов на каждом дорогостоящем шаге обработки целевой моделью.

Without speculative decoding:
  Generate 5 tokens: 5 × 30ms = 150ms

With speculative decoding (K=4):
  Draft 4 tokens: 4 × 1.5ms = 6ms
  1 target verification pass: ~35ms  (slightly longer than decode,
                                       processes K+1=5 positions)
  Expected accepted tokens per round:
    (1 - 0.80^5) / (1 - 0.80) ≈ 3.36 tokens
  Time per round: 6ms + 35ms = 41ms
  Time per token: 41ms / 3.36 ≈ 12.2ms
Speedup: 30ms → 12.2ms ≈ 2.5×

Ускорение зависит от совпадения между вариантом и целевым результатом. Простой текст с низкой энтропией позволяет использовать длинные варианты; неожиданные токены приводят к прекращению их принятия.

import torch
import torch.nn.functional as F

def speculative_decode(target_model, draft_model, input_ids,
                       max_new_tokens, K=4, temperature=1.0):
    """
    Conceptual speculative decoding loop.
    Real implementations handle KV cache management across both models.
    """
    generated = input_ids.clone()
    while generated.shape[1] - input_ids.shape[1] < max_new_tokens:
        # --- Draft phase ---
        draft_tokens = []
        draft_probs = []
        draft_input = generated.clone()
        for _ in range(K):
            with torch.no_grad():
                draft_logits = draft_model(draft_input).logits[:, -1, :]
            q = F.softmax(draft_logits / temperature, dim=-1)
            token = torch.multinomial(q, num_samples=1)
            draft_tokens.append(token)
            draft_probs.append(q)
            draft_input = torch.cat([draft_input, token], dim=1)
        # --- Verify phase: one target forward pass over all K+1 positions ---
        verify_input = torch.cat([generated] + draft_tokens, dim=1)
        with torch.no_grad():
            target_logits = target_model(verify_input).logits
        # target_logits[:, -K-1:, :] covers all K draft positions + bonus
        # --- Accept/reject ---
        accepted = 0
        for i in range(K):
            p = F.softmax(target_logits[:, -(K+1)+i, :] / temperature, dim=-1)
            q = draft_probs[i]
            token = draft_tokens[i]
            # Acceptance probability
            accept_prob = torch.min(
                torch.ones_like(p.gather(1, token)),
                p.gather(1, token) / (q.gather(1, token) + 1e-9)
            )
            if torch.rand(1) < accept_prob:
                generated = torch.cat([generated, token], dim=1)
                accepted += 1
            else:
                # Sample corrected token and stop this round
                corrected_dist = F.relu(p - q)
                corrected_dist = corrected_dist / corrected_dist.sum(dim=-1, keepdim=True)
                corrected_token = torch.multinomial(corrected_dist, num_samples=1)
                generated = torch.cat([generated, corrected_token], dim=1)
                break
        else:
            # All K accepted - take bonus token
            bonus_logits = target_logits[:, -1, :]
            p_bonus = F.softmax(bonus_logits / temperature, dim=-1)
            bonus_token = torch.multinomial(p_bonus, num_samples=1)
            generated = torch.cat([generated, bonus_token], dim=1)
    return generated

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

Когда варианты расходятся

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

Раннее прекращение: останавливайте глубокие слои при уверенности

Некоторые архитектуры позволяют выходить на промежуточных уровнях при высокой степени уверенности, тем самым экономя вычислительные ресурсы на обработке «простых» токенов.

Layer distribution of exits:Exit at layers 1–8  (very easy tokens like punctuation, articles):  15%
Exit at layers 9–16 (medium tokens, common continuations):           35%
Exit at layers 17–24 (harder tokens, named entities, numbers):       30%
Exit at layers 25–32 (full computation required):                    20%Weighted average layers executed:
  0.15 × 6 + 0.35 × 12 + 0.30 × 20 + 0.20 × 32
  = 0.90 + 4.20 + 6.00 + 6.40
  = 17.5 layers averageSpeedup vs always running 32 layers:
  32 / 17.5 ≈ 1.83×

Аккуратно оценивайте влияние на точность: ранний выход идет в ущерб качеству ради скорости и чувствителен к настройкам калибровки.

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

Спекулятивная декодировка изменяет цикл предложения токенов с использованием второй модели; ранний выход изменяет глубину обработки в рамках одной модели. Они по-разному решают связанные проблемы и иногда могут использоваться вместе с квантизацией, непрерывной группировкой данных и пагинацией KV-кэша.

Combined stack example:

Target: 7B model, BF16, FlashAttention, PagedAttention
  → Model: ~14 GB, memory-efficient attention, paged KV cache

Draft: 70M model, INT4, FlashAttention
  → Model: ~35 MB, near-zero memory overhead

Speculative decode:
  → with K=4, α=0.80
  → ~2.5× token generation speedup on long outputs

Full stack speedup vs FP32 no-optimization baseline:
  - Quantization: 2–2.3× throughput
  - FlashAttention: 20–40% attention latency reduction
  - Speculative decoding: 2–2.5× decode speedup (on eligible requests)

Combined: 5–8× improvement in end-to-end tokens/second

Когда каждый метод полезен

Спекулятивная декодировка эффективна, когда вероятность согласия высока и задержки обусловлены большим количеством шагов. Она неэффективна, когда проекты редко совпадают или накладные расходы на их создание превышают получаемую выгоду. Ранний выход полезен, когда многие токены легки для обработки и позволяет бюджет точности; он неэффективен при обработке сложных токенов или при плохо настроенной степени уверенности.

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

Система отслеживания показателей: коэффициент принятия, средняя длина принимаемых данных, разницы в оценке качества, уровень использования GPU и задержка p95. Оптимизации с помощью флагов функций. Сохраните возможность переключения на стандартную разборку данных. Имейте в виду, что оставшимся узким местом может быть пропускная способность памяти, сеть или процесс отрисовки на стороне клиента — а не только количество операций FLOPs, поэтому проводите профилирование перед применением любых техник.

Заполнение данных заранее и процесс разборки влияют на нагрузку на оборудование по-разному. Спекулятивная разборка и досрочный выход являются практичными инструментами при анализе кривых принятия и точности. Рассматривайте их как функции, используемые в производстве с панелями управления, а не как одноразовые тесты; они окажутся эффективными при реальном трафике.

Представьте себе целевую модель объемом 7 миллиардов параметров, обеспечивающую чат-функцию с ответами длиной от 50 до 150 токенов. Загрузка системного промпта объемом 2 тысячи токенов занимает много времени, но происходит редко за один раз; именно шаги декодирования определяют задержку, которую ощущает пользователь. Сокращение количества шагов декодирования с помощью спекулятивных принятий решений или уменьшение объема работы на каждом шаге путем досрочного завершения работает на улучшение восприятия скорости пользователем.

Чек-лист операций

  • Основные показатели p95 и качества.
  • Добавьте промежуточную модель, расположенную в том же месте, чтобы избежать задержек сети.
  • Ведите журнал гистограмм принятий решений.
  • Проводите тесты качества в режиме A/B на наборах фактической информации.
  • Следите за балансом использования CPU и GPU при запуске промежуточных моделей на разных устройствах.
  • Пересматривайте параметры после каждой замены токенизатора или процедуры финтюнинга.

Распространенные ошибки

Использование случайного, не связанного с задачей варианта; игнорирование влияния температуры на качество результата; объявление победы на этапе обработки данных без проверки качества; сочетание раннего завершения обработки с агрессивной квантизацией до появления галлюцинаций. Каждая из этих проблем поддается измерению — сначала с помощью инструментов.

Расширенные рекомендации для команд платформы

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

Более подробно о методе стекинга

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

Часто задаваемые вопросы

Влияет ли спекулятивный подход на результаты? При правильной реализации он должен соответствовать целевому распределению; проверяйте это с помощью парных тестов. Влияет ли досрочный выход на результаты? Да, поскольку он позволяет пропускать некоторые этапы обработки — учитывайте возникающие изменения. Можно ли генерировать текст на процессоре? Иногда; необходимо провести измерения. Есть ли это значение для маленьких моделей, работающих на устройстве? Часто оно меньше, чем для крупных моделей. Порядок приоритетов: сначала устраните проблемы с группировкой запросов и кэшированием, затем примените спекулятивные методы, и только потом — досрочный выход, если стек поддерживает его.

Пример сценария для лучшего понимания

Представьте себе целевую модель объемом 7 миллиардов параметров, обеспечивающую чат-функцию с ответами длиной от 50 до 150 токенов. Загрузка системного промпта объемом 2 тысячи токенов занимает много времени, но происходит редко за один раз; именно шаги декодирования определяют задержку, которую ощущает пользователь. Сокращение количества шагов декодирования с помощью спекулятивных принятий решений или уменьшение объема работы на каждом шаге через досрочный выход способствует снижению ощущаемой задержки.

Чек-лист операций

  • Основные показатели p95 и качества.
  • Использование промежуточной версии модели, размещенной в том же месте, чтобы избежать задержек сети.
  • Логирование гистограмм принятий решений.
  • Сравнение качества на наборах фактической информации в режиме A/B.
  • Контроль баланса между CPU и GPU при запуске промежуточных версий модели на разных устройствах.
  • Повторная проверка после каждой изменения токенизатора или параметров настройки модели.

Распространенные ошибки

Использование случайного, не связанного с задачей варианта; игнорирование влияния температуры на качество результата; объявление победы на этапе обработки данных без проверки качества; сочетание раннего завершения обработки с агрессивной квантизацией до появления галлюцинаций. Каждая из этих проблем поддается измерению — сначала с помощью инструментов.

Расширенные рекомендации для команд платформы

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

Более подробно о методе стекинга

Следует осторожно сочетать непрерывную группировку запросов с спекулятивными методами: длина черновиков влияет на предположения планировщика. Необходимо также объединять это с политиками удаления данных из кэша KV, чтобы длинные чаты не приводили к сбоям в работе системы. Кроме того, следует использовать кэширование промптов на этапе предварительной загрузки, чтобы избежать ситуаций, когда происходит «исправление декодирования», при этом остается избыточная загрузка ресурсов. Комплексный подход к проектированию обслуживания эффективнее, чем применение отдельных решений в критически важных участках работы системы.

Часто задаваемые вопросы

Влияет ли спекулятивный подход на результаты? При правильной реализации он должен соответствовать целевому распределению; проверяйте это с помощью парных тестов. Влияет ли досрочный выход на результаты? Да, поскольку он позволяет пропускать некоторые этапы обработки — учитывайте возникающие изменения. Можно ли генерировать текст на процессоре? Иногда; необходимо провести измерения. Есть ли это значение для маленьких моделей, работающих на устройстве? Часто оно меньше, чем для крупных моделей. Порядок приоритетов: сначала устраните проблемы с группировкой запросов и кэшированием, затем примените спекулятивные методы, и только потом — досрочный выход, если стек поддерживает его.

Числовая интуиция, проверенная на практике

Предположим, что стоимость одного целевого шага составляет 10 мс, а проект предлагает 5 токенов с средним уровнем принятия 60% для 3 токенов. Эффективная стоимость за принятый токен оказывается ниже, чем у обычных шагов с одним токеном, даже с учетом дополнительных затрат проекта, при условии стабильно высокого уровня принятия. Если уровень принятия снижается до примерно 1 токена, такая схема становится неэффективной. Именно из-за такой чувствительности панели управления превосходят анекдотические примеры.

Протокол регрессии качества

Перед глобальным внедрением протестируйте фиксированные запросы в задачах на проверку фактов, программирование и отклонение запросов. Сравнивайте показатели с одинаковым количеством токенов при настройке спекулятивных вариантов для точного совпадения распределения. Изучайте любые систематические отклонения. Для раннего выявления проблем отслеживайте процент успешных решений в задачах с оценкой качества и человеческие предпочтения, если они доступны.

Размещение оборудования

По возможности размещайте черновики и готовые версии на одном узле. Работа с черновиками на разных хостах приводит к сетевым задержкам, которые могут свести на нет все достижения. Следите за объемом памяти: две модели плюс кэш KV могут исчерпать ограничения памяти устройства, которое раньше спокойно вмещало только одну модель.

Планирование взаимодействий

Серверы, обрабатывающие данные пакетами непрерывно, должны учитывать изменчивость объема данных при обработке. Плохие алгоритмы планирования приводят к фрагментации пакетов и снижают эффективность использования ресурсов. Согласовывайте действия с ответственными за обслуживание; не меняйте настройки только в коде приложения.

Честность относительно оставшихся узких мест

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

Краткое резюме

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

Числовая интуиция, проверенная на практике

Предположим, что обработка одного шага занимает 10 мс, а проект предлагает 5 токенов с средним коэффициентом принятия 60% для 3 токенов. Эффективная стоимость за принятый токен оказывается ниже, чем при обработке одного токена, даже с учетом дополнительных затрат на подготовку проекта, при условии стабильного уровня принятия. Если коэффициент принятия снижается до примерно 1 токена, такая схема становится неэффективной. Именно из-за такой чувствительности дашборды превосходят анекдотические примеры.

Протокол регрессии качества

Прежде чем включить функцию глобально, протестируйте фиксированные запросы в тестах на проверку фактов, программировании и ситуациях отказа. Сравните показатели полной идентичности токенов при настройке спекулятивных алгоритмов для точного совпадения распределения. Изучите возможные систематические отклонения. Для досрочного вывода анализируйте процент успешных решений на задачах с оценкой качества и, при наличии данных, предпочтения людей.

Размещение оборудования

По возможности размещайте исходные данные и целевые результаты на одном узле. Размещение исходных данных на разных хостах увеличивает сетевую нестабильность, что может свести на нет достигнутые преимущества. Обращайте внимание на объем памяти: две модели плюс кэш KV могут исчерпать её ресурсы у устройства, которое ранее комфортно вмещало только одну модель.

Планирование взаимодействий

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

Честность относительно оставшихся узких мест

Даже после улучшения процесса декодирования пользователи могут по-прежнему ждать выполнения запросов к инструментам, получения данных или обработки Markdown на стороне клиента. Необходимо отслеживать процесс с начала до конца. Оптимизация в неверных областях тратит время инженеров впустую.

Краткое резюме

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

Числовая интуиция

Предположим, что обработка одного шага занимает 10 мс, а проектный вариант предлагает 5 токенов с средним коэффициентом принятия 60% для 3 токенов. Эффективная стоимость за принятый токен оказывается ниже, чем при обработке одного токена, даже с учетом дополнительных затрат проектного варианта, если уровень принятия остается высоким. Если коэффициент принятия снижается до примерно 1 токена, такая схема становится неэффективной. Именно из-за такой чувствительности дашборды превосходят анекдотические примеры.

Протокол контроля ухудшения качества

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

Размещение оборудования

По возможности размещайте версию черновика и финальную версию на одном узле. Работа черновиков на разных хостах приводит к сетевым колебаниям, которые могут свести на нет достигнутые результаты. Следите за объемом памяти: две модели плюс кэш KV могут исчерпать ограничения памяти устройства, которое ранее комфортно вмещало одну модель.

Планирование взаимодействий

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

Честность относительно оставшихся узких мест

Даже после улучшения процесса декодирования пользователи могут по-прежнему ждать выполнения запросов к инструментам, получения данных или обработки Markdown на стороне клиента. Необходимо отслеживать процесс с начала до конца. Оптимизация в неверных областях тратит время инженеров впустую.

Краткое резюме

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

Числовая интуиция

Предположим, что обработка одного шага занимает 10 мс, а проектный вариант предлагает 5 токенов с средним коэффициентом принятия 60% для 3 токенов. Эффективная стоимость за принятый токен оказывается ниже, чем при обработке одного токена, даже с учетом дополнительных затрат проектного варианта, если уровень принятия остается высоким. Если коэффициент принятия снижается до примерно 1 токена, такая схема становится неэффективной. Именно из-за такой чувствительности дашборды превосходят анекдотические примеры.

Протокол контроля ухудшения качества

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

Размещение оборудования

По возможности размещайте версию черновика и финальную версию на одном узле. Работа черновиков на разных хостах приводит к сетевым колебаниям, которые могут свести на нет достигнутые результаты. Следите за объемом памяти: две модели плюс кэш KV могут исчерпать ограничения памяти устройства, которое ранее комфортно вмещало одну модель.

Планирование взаимодействий

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

Честность относительно оставшихся узких мест

Даже после улучшения процесса декодирования пользователи могут по-прежнему ждать выполнения запросов к инструментам, загрузки данных или обработки Markdown на стороне клиента. Необходимо отслеживать процесс с начала до конца. Оптимизация в неверных областях тратит время инженеров впустую.

Краткое резюме

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