# Как оптимизировать инференс языковых моделей: от архитектуры до vLLM

Источник: https://www.youtube.com/watch?v=fcgPYo3OtV0
Канал: Stanford Online
Опубликовано: 19.05.2025

---

## Искусство эффективности: как оптимизировать инференс языковых моделей
[[JUMP:00:05]]

Инференс (процесс генерации ответов уже обученной моделью) перестал быть просто технической задачей «демо-версии чат-бота». Сегодня это фундамент работы любых LLM-продуктов — от автодополнения кода в **Cursor** до обработки больших массивов данных в пакетном режиме, а также критическая часть обучения с подкреплением (RL). Поскольку обучение модели — это разовая инвестиция, а инференс — повторяющаяся, именно он определяет экономическую эффективность развертывания нейросетей в реальном мире.

### 🛠 Метрики и математика инференса
[[JUMP:03:10]]

Понимание того, почему генерация «медленная», начинается с анализа вычислительной сложности.

*   **TTFT (Time to First Token):** Время ожидания первого токена пользователем, критично для интерактивных приложений.
*   **Latency (Задержка):** Скорость генерации последующих токенов.
*   **Throughput (Пропускная способность):** Общее количество токенов, генерируемых системой в единицу времени, особенно важно для пакетной обработки.

Основная сложность заключается в том, что в отличие от обучения, где можно параллельно обрабатывать все токены последовательности (используя всю мощь тензорных вычислений), инференс — процесс **авторегрессионный**. Генерация текущего токена зависит от всех предыдущих, что превращает задачу из «вычислительно ограниченной» (compute-bound) в «ограниченную памятью» (memory-bound). Арифметическая интенсивность (отношение операций к объему передачи данных) падает, из-за чего современные GPU, такие как **H100**, часто простаивают, ожидая данные из памяти.

### 🧠 Борьба за KV-кэш
[[JUMP:16:06]]

Ключевой «пожиратель» памяти при инференсе — это **KV-кэш** (Key-Value Cache). Чтобы не пересчитывать одни и те же промежуточные значения для каждого нового токена, система кэширует ключи и значения для всех слоев и голов внимания. Поскольку инференс ограничен памятью, уменьшение размера этого кэша — прямой путь к ускорению.

Существует несколько подходов к решению этой проблемы:

1.  **Group Query Attention (GQA):** Компромисс между multi-head и multi-query attention. Мы уменьшаем количество ключей и значений, оставляя больше запросов (queries). Это снижает объем памяти и позволяет увеличивать размер батча.
2.  **Multi-Head Latent (MLA):** Предложенный командой **DeepSeek** подход, где вместо простого уменьшения количества голов значения проецируются в пространство меньшей размерности.
3.  **Cross-Layer Attention (CLA):** Совместное использование проекций ключей и значений между разными слоями трансформера, что позволяет еще сильнее сжать кэш.
4.  **Local Attention (Локальное внимание):** Ограничение окна внимания только прошлыми $K$ токенами. Это делает размер кэша константным, а не растущим вместе с длиной последовательности.

### 🚀 Радикальная архитектура и «шорткаты»
[[JUMP:52:54]]

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

*   **State Space Models (SSM):** Модели вроде **Mamba** стремятся заменить квадратичную сложность внимания на линейную, используя динамические системы и RNN-подобную структуру.
*   **Диффузионные модели:** Генерируют все токены параллельно, а затем итеративно уточняют их. Хотя это всё еще экспериментальная область для текста, такие модели показывают невероятную скорость генерации.
*   **Спекулятивное декодирование (Speculative Decoding):** «Золотой стандарт» точного инференса. Маленькая, быстрая модель-драфт генерирует предположения, которые затем параллельно проверяются большой целевой моделью. Это позволяет получить ускорение в разы, сохраняя точность «большой» модели.

### ⚙️ Системная оптимизация
[[JUMP:1:18:04]]

На уровне инфраструктуры решающую роль играют идеи из операционных систем:

*   **Selective Batching:** Пакетная обработка запросов разной длины, где вычисления для внимания проводятся отдельно, а MLP-слои (основной объем вычислений) «склеиваются» в батч.
*   **PagedAttention:** Решение, стоящее за **vLLM**, использует механизм виртуальной памяти для разбиения KV-кэша на фрагменты. Это устраняет внешнюю фрагментацию и позволяет динамически управлять памятью при разной длине запросов.