English translation is not available yet. Showing Russian content.

Как вы измеряете и оптимизируете TTFT (Time To First Token) и TPOT (Time Per Output Token)?

Краткий тезис

TTFT (Time To First Token) — это задержка до генерации первого токена ответа, критичная для восприятия отзывчивости системы. TPOT (Time Per Output Token) — время на каждый последующий токен, определяющее скорость генерации длинных ответов. Обе метрики напрямую влияют на пользовательский опыт в RAG|agentic RAG (агентные RAG-системы), где требуется быстрая итерация вызовов LLM. Оптимизация TTFT фокусируется на ускорении фазы prefill (заполнения контекста), а TPOT — на ускорении фазы decode (авторегрессивной генерации). Ключевые методы: chunked prefill для TTFT, speculative decoding для TPOT, а также использование меньших моделей и аппаратных оптимизаций (Attention 2|Flash Attention, KV cache quantization).


1. Термины: TTFT и TPOT

TTFT (Time To First Token) — время от отправки запроса до получения первого токена ответа. Включает:

  • Сетевую задержку
  • Обработку запроса на сервере (предобработка, токенизация)
  • Prefill — прямой проход через все слои модели для вычисления скрытых состояний всех токенов входного контекста (prompt). Эта фаза выполняется один раз за запрос и является вычислительно затратной, особенно для длинных контекстов.
  • Начало генерации первого токена (обычно тривиально после prefill).

TPOT (Time Per Output Token) — среднее время генерации одного токена после первого. Измеряется как (общее время генерации - TTFT) / (количество сгенерированных токенов - 1). Эта метрика отражает скорость decode — авторегрессивной фазы, где каждый следующий токен генерируется на основе предыдущих, с использованием KV cache (кэша ключей и значений).

МетрикаФазаЗависит отТипичные значения (для LLM 7B на A100)
TTFTPrefillДлина промпта, размер модели, аппаратное обеспечение100–500 мс для коротких промптов, до нескольких секунд для длинных
TPOTDecodeРазмер модели, batch size, эффективность KV cache10–50 мс на токен (для batch size=1)

2. Измерение TTFT и TPOT

2.1 Инструменты измерения

2.2 Пример кода на Python (синхронный)

import time
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

model_name = "microsoft/Phi-3-mini-4k-instruct"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(model_name, device_map="auto")

prompt = "Explain the concept of TTFT in one sentence."
inputs = tokenizer(prompt, return_tensors="pt").to("cuda")

# Замер TTFT
start = time.time()
with torch.no_grad():
    outputs = model.generate(**inputs, max_new_tokens=50, output_scores=False)
ttft = time.time() - start  # грубо, включает часть decode

# Более точный замер: первый токен
start = time.time()
with torch.no_grad():
    # Генерируем только первый токен
    logits = model(**inputs).logits
    first_token = torch.argmax(logits[:, -1, :], dim=-1)
ttft = time.time() - start

# Замер TPOT (среднее на токен после первого)
start = time.time()
with torch.no_grad():
    generated = model.generate(**inputs, max_new_tokens=100, pad_token_id=tokenizer.eos_token_id)
total_time = time.time() - start
num_tokens = generated.shape[1] - inputs.input_ids.shape[1]
tpot = (total_time - ttft) / (num_tokens - 1) if num_tokens > 1 else 0

print(f"TTFT: {ttft*1000:.1f} ms")
print(f"TPOT: {tpot*1000:.1f} ms/token")

2.3 Факторы, влияющие на точность

  • Холодный старт: первый запрос после загрузки модели включает инициализацию CUDA, компиляцию графа. Измерения нужно проводить после прогрева (несколько запросов).
  • Batch size: при batch > 1 TTFT и TPOT могут расти из-за конкуренции за память и вычисления.
  • Длина промпта: TTFT линейно растёт с длиной промпта (O(n) для prefill).
  • Длина генерации: TPOT может увеличиваться к концу генерации из-за роста KV cache.

3. Оптимизация TTFT (Prefill)

3.1 Chunked Prefill

Разбиваем длинный промпт на чанки и обрабатываем их параллельно или последовательно с перекрытием. Позволяет уменьшить TTFT для длинных контекстов ценой небольшого увеличения TPOT.

Реализация: в библиотеках vllm и TGI поддерживается через параметр --enable-chunked-prefill.

3.2 Prefix Caching (кэширование префиксов)

Если часто используются одинаковые начальные части промптов (например, системные сообщения), можно кэшировать их KV-состояния. TTFT для таких запросов снижается до времени обработки только уникального хвоста.

3.3 Меньшая модель

Использование модели меньшего размера (например, 3B вместо 7B) сокращает TTFT в 2–3 раза. Компромисс — возможное снижение качества.

3.4 Аппаратные ускорители


4. Оптимизация TPOT (Decode)

4.1 Speculative Decoding

Генерируем несколько токенов «черновиком» (draft model) быстро, затем проверяем их целевой моделью. Если черновик угадан, TPOT снижается в 2–3 раза. Метод особенно эффективен для batch size = 1.

Пример: draft model — 125M, target model — 7B. TPOT падает с 30 мс до 12 мс.

4.2 KV Cache Quantization

Сжатие KV cache до 4-бит или 8-бит уменьшает объём памяти и ускоряет decode за счёт снижения latency доступа к памяти.

4.3 Flash Decoding

Оптимизация decode через параллельную обработку нескольких запросов в batch (даже если batch size = 1, можно использовать внутренний параллелизм).

4.4 Меньшая модель

Как и для TTFT, уменьшение модели напрямую ускоряет decode.

4.5 Batching

Объединение нескольких запросов в один batch увеличивает throughput (токенов/сек), но может повысить TPOT для каждого отдельного запроса из-за конкуренции.


5. Компромиссы и балансировка

СтратегияВлияние на TTFTВлияние на TPOTКогда применять
Chunked prefill↓ (сильно)↑ (незначительно)Длинные промпты (>2K токенов)
Speculative decoding↓ (сильно)Длинная генерация, малый batch
Меньшая модельКогда качество допустимо
KV cache quantizationВсегда, если память ограничена
Batch size > 1↑ (конкуренция)↑ (конкуренция)Высокий трафик, не критична latency

Ключевой компромисс: TTFT и TPOT часто конфликтуют. Например, chunked prefill увеличивает TPOT, а speculative decoding не влияет на TTFT. Выбор зависит от сценария: для чат-ботов важен низкий TTFT, для генерации длинных отчётов — низкий TPOT.


6. Инструменты мониторинга в production

  • vLLM — встроенные метрики через --metrics (Prometheus endpoint).
  • TGI — логи TTFT и TPOT в stdout.
  • MLflow / Weights & Biases — для экспериментов.
  • Grafana + Prometheus — дашборды для отслеживания в реальном времени.

Пример дашборда:

Метрика: llm_request_ttft_seconds (гистограмма)
Метрика: llm_request_tpot_seconds (гистограмма)

7. Пет-проект для закрепления

Задача: Написать бенчмарк для сравнения TTFT и TPOT на двух моделях (например, Phi-3-mini-4k и TinyLlama) с разными длинами промптов и настройками (chunked prefill, speculative decoding).

Инструменты:

Шаги:

  1. Загрузить две модели.
  2. Подготовить набор промптов разной длины (128, 512, 1024, 2048 токенов).
  3. Для каждого промпта измерить TTFT и TPOT (с прогревом).
  4. Повторить для разных конфигураций: с chunked prefill (если поддерживается), с speculative decoding (если есть draft model).
  5. Построить графики зависимости TTFT и TPOT от длины промпта.
  6. Сделать выводы: какая модель быстрее, какие оптимизации эффективны.

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


8. Связь с другими вопросами

ВопросТема
7Как вы уменьшаете latency RAG-системы (время ответа)?
10Что такое Self-RAG и когда его использовать?
12Какие методы оптимизации инференса LLM вы знаете?
15Что такое speculative decoding и как он работает?
20Как работает chunked prefill и когда его применять?

9. Навигация


Навигация