中文翻译暂不可用,显示俄语原文。

Как вы деплоите LLM с requirement <100ms latency при throughput 1000 req/s? Архитектура.

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

Деплой LLM с latency <100ms и throughput 1000 req/s требует многоуровневой архитектуры: L7-балансировщик распределяет запросы между несколькими репликами vLLM, каждая из которых использует адаптивный батчинг и спекулятивное декодирование с маленькой draft-моделью. Redis выступает распределённым KV-cache для ускорения повторяющихся запросов. Аппаратная основа — NVIDIA H100 или B200 с оптимизированной памятью и межсоединениями. Ключевые метрики — P99 latency и batch size — мониторятся для автоскейлинга.

1. Термины и требования

Latency — время от отправки запроса до получения первого токена ответа (TTFT) или полного ответа. Для <100ms обычно речь о TTFT (time to first token). Throughput — количество обработанных запросов в секунду (req/s). 1000 req/s — высоконагруженный сценарий (например, чат-бот для миллионов пользователей).

P99 latency — 99-й перцентиль задержки: 99% запросов должны укладываться в 100ms. Это жёстче среднего.

Batch size — количество запросов, обрабатываемых моделью за один проход. Чем больше batch, тем выше throughput, но растёт latency из-за ожидания накопления батча.

KV-cache — кэш ключей и значений внимания, ускоряющий генерацию повторяющихся префиксов (например, системный промпт). Speculative decoding — техника, при которой маленькая draft-модель генерирует несколько токенов, а model|большая модель проверяет их, экономя время на последовательных forward-проходах.

2. Балансировка запросов: L7 Load Balancer

Первый уровень — L7 (application layer) балансировщик (например, NGINX, Envoy, HAProxy). Он распределяет входящие HTTP/gRPC запросы по нескольким репликам vLLM на основе round-robin или least connections. Для минимизации latency балансировщик должен быть географически близок к клиентам и использовать keep-alive соединения.

Конфигурация NGINX (фрагмент):

upstream llm_backend {
    least_conn;
    server 10.0.1.1:8000 max_fails=3 fail_timeout=30s;
    server 10.0.1.2:8000;
    server 10.0.1.3:8000;
}

server {
    listen 443 ssl http2;
    location /v1/chat/completions {
        proxy_pass http://llm_backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

Health checks — балансировщик периодически проверяет /health эндпоинт каждой реплики и исключает нездоровые.

3. Инференс-сервер: vLLM с адаптивным батчингом

vLLM — open-source библиотека для эффективного инференса LLM. Ключевые фичи:

  • PagedAttention — эффективное управление KV-cache, уменьшающее фрагментацию памяти.
  • Continuous batching (адаптивный батчинг) — запросы добавляются в батч по мере поступления, не дожидаясь заполнения фиксированного размера. Это снижает latency для ранних запросов.

Пример запуска vLLM с оптимизациями:

python -m vllm.entrypoints.openai.api_server \
    --model meta-llama/Meta-Llama-3-70B \
    --tensor-parallel-size 4 \
    --pipeline-parallel-size 2 \
    --max-num-seqs 256 \
    --max-model-len 4096 \
    --gpu-memory-utilization 0.95 \
    --enable-chunked-prefill \
    --speculative-model meta-llama/Llama-3.2-1B \
    --num-speculative-tokens 5

Параметры:

  • tensor-parallel-size — число GPU для тензорного параллелизма (разделение слоёв).
  • pipeline-parallel-size — число GPU для конвейерного параллелизма (разделение по слоям).
  • max-num-seqs — максимальный размер батча.
  • enable-chunked-prefill — разбивает префилл (обработку промпта) на чанки, уменьшая TTFT.
  • speculative-model — путь к draft-модели для спекулятивного декодирования.

Адаптивный батчинг динамически выбирает размер батча на основе текущей загрузки. При низкой нагрузке батчи маленькие (низкая latency), при высокой — большие (высокий throughput). vLLM использует планировщик, который максимизирует throughput при соблюдении SLA по latency.

4. Распределённый KV-cache: Redis

Для запросов с одинаковыми префиксами (например, системный промпт, история диалога) можно кэшировать KV-cache в Redis (или Memcached). Это сокращает время префилла для повторяющихся контекстов.

Архитектура:

  • Каждый запрос содержит hash префикса (например, SHA256 первых N токенов).
  • vLLM перед префиллом проверяет Redis: если ключ существует, загружает готовый KV-cache и достраивает только новые токены.
  • TTL для кэша — несколько минут (зависит от частоты обновления контекста).

Пример Redis-команды:

import redis
r = redis.Redis(host='redis-cluster', port=6379, decode_responses=True)
cache_key = f"kv_cache:{hash_prefix}"
cached = r.get(cache_key)
if cached:
    # загрузить в GPU memory
    pass
else:
    # вычислить и сохранить
    r.setex(cache_key, 300, serialized_cache)

Проблемы:

  • Сериализация/десериализация KV-cache (размер может быть ~1-10 MB на запрос) — требует быстрой сети (RDMA).
  • Синхронизация при обновлении модели — инвалидация кэша.

5. Speculative Decoding

Speculative decoding ускоряет генерацию, используя маленькую draft-модель (например, 1B параметров) для быстрой генерации K токенов, а большая модель (70B) проверяет их параллельно. Если draft-модель угадала, мы получаем K токенов за один forward большой модели. Типичное ускорение — 2-3x.

Процесс:

  1. Draft-модель генерирует K токенов (например, 5) авторегрессивно.
  2. Большая модель делает один forward на всех K+1 позициях (включая исходный токен).
  3. Сравниваются распределения: если вероятность draft-токена выше порога, он принимается; иначе — rejection sampling.
  4. Принятые токены возвращаются, rejected — заменяются на токен большой модели.

Выбор draft-модели:

  • Должна быть достаточно маленькой (1-3B), чтобы latency её генерации была мала.
  • Должна иметь высокий acceptance rate (доля принятых токенов) — обычно >0.7 для близких по домену моделей.
  • Можно использовать Medusa (дополнительные головы на большой модели) вместо отдельной draft-модели.

6. Аппаратное обеспечение: H100 vs B200

ПараметрNVIDIA H100 SXMNVIDIA B200
FP8 TFLOPS19794500
HBM3 память80 GB192 GB
Пропускная способность памяти3.35 TB/s8 TB/s
NVLink900 GB/s1800 GB/s
TDP700 W1000 W
Цена (ориентир)~$30k~$50k

Для 1000 req/s с latency <100ms потребуется кластер из нескольких GPU. Пример расчёта для Llama-3-70B:

  • Одна H100 обрабатывает ~50 req/s (с speculative decoding и batch=64).
  • Для 1000 req/s нужно ~20 H100 (5 узлов по 4 GPU).
  • B200 даёт ~2x больше throughput за счёт большей памяти и пропускной способности, поэтому хватит 10 B200.

Конфигурация узла:

  • 4-8 GPU H100/B200 с NVLink.
  • CPU: AMD EPYC или Intel Xeon с высокими частотами.
  • RAM: 512 GB+ для хранения модели и KV-cache.
  • Сеть: InfiniBand HDR (200 Gbps) или NVIDIA Spectrum-X для межузлового общения.

7. Мониторинг и автоскейлинг

Ключевые метрики:

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

Пример HPA на основе Prometheus:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: vllm-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: vllm
  minReplicas: 5
  maxReplicas: 20
  metrics:
  - type: Pods
    pods:
      metric:
        name: p99_latency_ms
      target:
        type: AverageValue
        averageValue: 80

8. Оптимизации и компромиссы

ТехникаВлияние на latencyВлияние на throughputСложность
Адаптивный батчинг- (увеличивает при высокой нагрузке)+Низкая
Speculative decoding-- (снижает)+Средняя
KV-cache (Redis)-- (снижает TTFT)+ (при hit)Высокая
Tensor parallelism- (снижает за счёт коммуникации)++Средняя
Pipeline parallelism- (снижает)+Средняя
Chunked prefill-- (снижает TTFT)0Низкая

Компромисс: увеличение batch size повышает throughput, но может поднять P99 latency выше 100ms. Необходимо найти оптимальный max-num-seqs через нагрузочное тестирование.

9. Пример архитектуры (диаграмма текстом)

Client → L7 LB (NGINX) → vLLM Replica 1 (GPU: H100x4)
                         → vLLM Replica 2 (GPU: H100x4)
                         → vLLM Replica 3 (GPU: H100x4)
                         → vLLM Replica 4 (GPU: H100x4)
                         → vLLM Replica 5 (GPU: H100x4)
                              |
                              ├── Redis Cluster (KV-cache)
                              └── Monitoring (Prometheus + Grafana)

Каждая реплика vLLM использует speculative decoding с draft-моделью (загружена на те же GPU или отдельные). Redis кластер из 3-5 нод для отказоустойчивости.

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

Задача: Развернуть Llama-3-8B с latency <50ms и throughput 100 req/s на одной H100 (или эмулировать на CPU с меньшими требованиями).

Инструменты: Docker, vLLM, Redis, Locust (для нагрузочного тестирования), Prometheus + Grafana.

Шаги:

  1. Запустить vLLM с моделью Llama-3-8B, включив continuous batching и chunked prefill.
  2. Настроить Redis и модифицировать vLLM (или использовать встроенный prefix caching) для кэширования KV-cache.
  3. Написать скрипт на Python с использованием openai клиента для отправки запросов с разными префиксами.
  4. Запустить Locust с 50 concurrent users, измеряя latency и throughput.
  5. Настроить Prometheus для сбора метрик vLLM (экспортёр уже встроен) и визуализировать в Grafana.
  6. Поэкспериментировать с max-num-seqs и num-speculative-tokens, найти оптимальные значения.

Ожидаемый результат: Достичь P99 latency <50ms при 100 req/s, продемонстрировать снижение TTFT при использовании KV-cache (hit ratio >50%).

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

ВопросТема
7Как вы уменьшаете latency RAG-системы?
10Что такое Self-RAG и когда его использовать?
1Как бы вы спроектировали RAG-систему для 10 000 документов?
9Как вы обновляете документы в существующей RAG-системе?
2Как вы решаете проблему lost in the middle?
3Какие стратегии chunking'а вы знаете?

Навигация