Решения

Throughput vs Latency: баланс в продакшене

Задача страницы. Дать практичный рецепт, как на https://cloudcompute.ru балансировать пропускную способность (QPS/TPS/FPS) и латентность (TTFT/p95) на GPU‑сервисах: LLM‑инференс, CV/видеоаналитика, рендер/симуляции. Разобрать архитектуры, настройки батчинга/конкурентности, метрики и экономику.

TL;DR

  • Онлайн‑интерактив = приоритет латентности, короткие батчи, жёсткое ограничение очередей. Офлайн/массовая генерация = приоритет throughput, агрессивный батчинг и пайплайнинг. См. https://cloudcompute.ru/solutions/interruptible-patterns/.
  • Разделяйте префилл/декод (LLM) и ingest/обработку (CV): разные SLO, разные батчеры.
  • Динамический батчинг = окно ожидания (Δ) + цели p95: подбирайте Δ так, чтобы TTFT(p95) укладывался в бюджет.
  • Микробатчинг + потоковая выдача: отдавайте первые токены/кадры сразу, остальное — батчируйте.
  • Считайте всё: Little’s Law (L≈λW), ρ≈λ·S (загрузка), tail‑латентность растёт резко при ρ→1. Наблюдаемость: https://cloudcompute.ru/solutions/monitoring-logging/.
  • Экономика: Cost_per_query падает с ростом батча до порога SLO, дальше растёт из‑за штрафов за задержки и ретраи. Планируйте на https://cloudcompute.ru/solutions/cost-planner/.
  • GPU‑тюнинг: смешанная точность (BF16/FP8), pinned memory, zero‑copy, KV‑кэш INT8 — см. https://cloudcompute.ru/solutions/fp8-bf16/ и https://cloudcompute.ru/solutions/performance-tuning/.
  • Мульти‑GPU: шардинг и роутинг запросов без cross‑GPU блокировок — см. https://cloudcompute.ru/solutions/multi-gpu/.

Сценарии

  • LLM‑чат/агенты (On‑Demand): SLO по TTFT и p95‑латентности, микробатчинг с малым окном Δ, стриминг токенов (SSE/WebSocket). См. https://cloudcompute.ru/solutions/gradio-fastapi/.
  • API генерации (офлайн/пакеты): большие батчи, длинные окна Δ, прерываемые задания чанками ≤ 120 сек.
  • Видеоаналитика RTSP: стабильный FPS, ring‑buffer 200–500 мс, NVDEC/NVENC, drop‑политики.
  • RAG/поиск/эмбеддинги: батчируйте запросы эмбеддинга, для поиска — кэш/индексы на GPU.
  • Симуляции/цифровые двойники: частота обновления UI/сенсоров важнее общей пропускной — низкое Δ, backpressure в ingest.

Архитектуры/пайплайны

A) Онлайн LLM‑сервис (низкая латентность)

				
					Client → API Gateway → Admission Control (слайс по SLO)
          → Scheduler (prefill queue / decode queue)
              → Microbatcher(Δ_small) → GPU Worker(s)
          → SSE/WebSocket (стриминг токенов)
Метрики: TTFT, tps_tok_s, p95 latency, q_len_prefill/decode, gpu_util/hbm

				
			

B) Офлайн генерация/аналитика (высокий throughput)

				
					Job Queue → N Executors (Docker)
             ├─ Batcher(Δ_large)
             ├─ GPU Worker(s)
             └─ NVMe Cache → Хранилище "тёплое/холодное"
Режим: Interruptible, чанк ≤ 120 сек, ретраи, идемпотентность
				
			

C) CV/Видео поток (стабильный FPS)

				
					RTSP/USB → Ingest → Ring Buffer → Preprocess (resize/normalize)
                → Microbatcher(кадры×камеры) → GPU Inference
                → Postproc → Event Bus/SSE
Алгоритм drop: oldest/skip‑frame при backlog > порог

				
			

D) Мульти‑GPU/мульти‑нод

				
					Router → [Node1 GPU0..k] ... [NodeN GPU0..k]
Политики: sticky по контексту/длине запроса, без cross‑GPU зависимостей
				
			

Профили GPU / VRAM / ориентиры

Ориентиры для целевой загрузки U≈0.7 и запасе VRAM ≥20%. Реальные значения зависят от модели/сцены/кодека.

Профиль

Видеопамять

LLM (интерактив)

Эмбеддинги/батчи

Видео/CV

Рекомендации

24 ГБ (Compact)

24 ГБ

малые модели, короткий контекст; TTFT приоритет, Δ≤10–20 мс

батчи 16–64, Δ≤50–80 мс

1080p@30–60, 1–2 потока

On‑Demand/минимальный батч, NVENC ≤ 1–2 сессий

48 ГБ (Balanced)

48 ГБ

средние модели, средний контекст; Δ≤30–60 мс

батчи 64–256, Δ≤100–200 мс

1080p@60 + 1–2 NVENC

Смешанный режим: online + офлайн батчи

80 ГБ (HQ)

80 ГБ

крупные модели/4K UI; Δ≤50–100 мс

батчи 256–1k, Δ≤200–400 мс

4K@30–45, 3–4 NVENC

Максимум throughput, изоляция очередей

Конфиги и скелеты

1) Модель‑сервер (динамический батчинг, квоты)

				
					model:
  name: "service-llm"
  batching:
    enable: true
    preferred_batch_sizes: [4, 8, 16, 32]
    max_queue_delay_microseconds: 60000   # Δ = 60 мс для online; 200–400 мс для офлайна
  instance_groups:
    - kind: "KIND_GPU"
      count: 1
  scheduling:
    priority_levels:
      - name: "realtime"   # UI/операторские
        max_concurrency: 32
      - name: "bulk"       # офлайн
        max_concurrency: 256
limits:
  max_pending_requests: 2000
  timeout_ms: 5000


				
			

2) Политика приёма запросов (FastAPI, SLO‑aware)

				
					from fastapi import FastAPI, Request, HTTPException
import time, asyncio, queue

TARGET_P95_MS = 800
MAX_INFLIGHT = 64           # конкарренси online
Q = asyncio.Semaphore(MAX_INFLIGHT)

app = FastAPI()

@app.middleware("http")
async def admission(request: Request, call_next):
    # Бюджет очереди из Little's Law: W≈L/λ. Если backlog растёт — 503.
    inflight = MAX_INFLIGHT - Q._value
    if inflight > MAX_INFLIGHT * 0.9:
        raise HTTPException(503, "busy")
    start = time.perf_counter()
    async with Q:
        resp = await call_next(request)
    dt_ms = (time.perf_counter() - start) * 1000
    if dt_ms > TARGET_P95_MS:
        # сигнал автоскейлеру/батчеру уменьшить Δ
        resp.headers["X-SLO-HINT"] = "reduce_delta"
    return resp


				
			

3) Стриминг токенов (ранний ответ + пайплайнинг)

				
					from fastapi import FastAPI
from fastapi.responses import StreamingResponse

app = FastAPI()

@app.get("/generate")
def generate(prompt: str):
    def stream():
        # Сразу отправляем первые токены (низкая TTFT)
        for tok in llm.generate_stream(prompt, delta_ms=20, max_new_tokens=256):
            yield f"data: {tok}\n\n"
    return StreamingResponse(stream(), media_type="text/event-stream")


				
			

4) Настройки CV‑батчера (камеры×кадры)

				
					cv_batcher:
  max_batch_frames: 32          # суммарно по камерам
  max_wait_ms: 30               # удержание под батч ≤ 1 кадра при 30 FPS
  drop_policy: "oldest"         # при backlog > 3×frame_time
  ring_buffer_ms: 300
				
			

Наблюдаемость, метрики, алерты

См. https://cloudcompute.ru/solutions/monitoring-logging/ и https://cloudcompute.ru/solutions/llm-inference/observability/.

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

  • Очереди: q_len_prefill, q_len_decode, event_backlog, inflight.
  • Латентность: ttft_ms (p50/p95), latency_ms (p50/p95), inter_token_ms/tps_tok_s.
  • Throughput: qps, fps, tokens_s, batch_size_eff.
  • GPU: gpu_util_pct, gpu_mem_used_gb, sm_efficiency_pct, pcie_tx_mb_s, enc_sessions.
  • I/O: i/o_backlog_sec, nvme_write_mb_s, net_rtt_ms (p95).
  • Качество: бизнес‑метрики (accuracy/PSNR/etc) на контрольных наборах.

Алерты (примеры)

  • ttft_ms(p95) > SLO 5 мин → сократить Δ, уменьшить batch, увеличить инстансы.
  • q_len_* монотонно растёт > N → включить backpressure/503, масштабировать воркеры.
  • gpu_util_pct < 30% при qps высоком → узкое место вне GPU (I/O/CPU/кодек).
  • gpu_mem_used_gb/vram > 0.9 → уменьшить контекст/батч, включить INT8/FP8 (см. https://cloudcompute.ru/solutions/fp8-bf16/).
  • frame_drop_pct > 1% в CV → снизить FPS/битрейт, увеличить ring_buffer_ms.

Экономика и формулы

Сервисные соотношения

ρ ≈ λ · S            # загрузка (λ — запросы/сек, S — среднее время обслуживания)

W ≈ L / λ            # Little’s Law: среднее время в системе

Wq растёт ≈ ρ/(1-ρ)  # очередь резко растёт при ρ → 1 (инженерная эвристика)

QPS ≈ concurrency / service_time

LLM (стоимость токенов) — см. также https://cloudcompute.ru/solutions/fp8-bf16/

EffCostPerHour = (c_gpu * N_gpu) / U

TokensPerHour  = TPS_tok_s * 3600 * N_gpu

Cost_per_1000_tok = EffCostPerHour / (TokensPerHour / 1000)

TTFT ≈ queue_delay(Δ) + prefill_time

Динамический батчинг

Latency_batch ≈ queue_delay(Δ) + service_time(batch)

Throughput ↑ с ростом batch, но TTFT ↑ из-за queue_delay.

Оптимум: минимизировать Cost_per_query при TTFT(p95) ≤ SLO.

CV/Видео (камеры×кадры)

FPS_eff ≈ min(FPS_in, GPU_capacity(batch, model))

Cost_per_camera_hour ≈ (c_gpu * α_render + c_gpu * α_infer) / U

Безопасность/политики

  • Изоляция очередей: разные priority‑классы (realtime/bulk), лимиты по арендаторам.
  • Rate limiting и admission: защищает от штормов запросов, предотвращает деградацию tail‑латентности.
  • Ключи/секреты — только в переменных окружения/секрет‑хранилищах (см. https://cloudcompute.ru/solutions/security/).
  • PII/логирование: не логируйте payload; суммарные метрики вместо сырых данных.
  • Ретеншн: логи/бэги/трейсы с ротацией, «тёплое/холодное» хранение — https://cloudcompute.ru/solutions/storage-data/.

Траблшутинг

Симптом

Причина

Решение

TTFT(p95) вырос

Окно Δ велико или backlog

Уменьшите Δ, лимитируйте inflight, увеличьте воркеры.

GPU недогружен при высокой очереди

Узкое место I/O/CPU

Профилируйте, включите pinned memory/zero‑copy, разгрузите препроцесс.

«Пила» латентности

Пере‑агрессивный автоскейлинг/батчинг

Стабилизируйте Δ, введитесь гистерезис, фиксируйте min/max инстансы.

Head‑of‑line blocking

Разнородные запросы в одном батче

Сегментируйте очереди (по длине контекста/времени запроса).

Падение TPS при росте batch

VRAM/кэш переполнены

Уменьшите batch или dtype KV‑кэша (INT8/FP8), см. /solutions/fp8-bf16/.

CV: drop кадров > 1%

Малый ring‑buffer, слабый NVENC

Увеличьте ring‑buffer, снизьте FPS/битрейт, проверьте NVENC‑сессии.

Пики p99

Холодный старт, миграции

Предпрогрев моделей, пинning воркеров, sticky‑routing.

503/таймауты у клиентов

Admission слишком жёсткий

Разделяйте классы трафика, увеличьте квоты realtime.

Как запустить в cloudcompute.ru

  1. Шаблон (Docker/SSH/Jupyter): https://cloudcompute.ru/solutions/templates/.
  2. Режим: On‑Demand для UI/чатов (низкое Δ, строгие SLO), Interruptible для батчей (Δ↑, throughput↑). См. https://cloudcompute.ru/solutions/interruptible-patterns/.
  3. Профиль GPU: 24 ГБ / 48 ГБ / 80 ГБ — см. таблицу профилей.
  4. Модель‑сервер: включите динамический батчинг и приоритизацию; для LLM — разделённые очереди префилл/декод. См. https://cloudcompute.ru/solutions/triton-inference-server/.
  5. Наблюдаемость: экспорт p50/p95, очереди, gpu_util/hbm — по гайду https://cloudcompute.ru/solutions/monitoring-logging/ и https://cloudcompute.ru/solutions/llm-inference/observability/.
  6. Тюнинг: BF16/FP8, KV‑кэш INT8, pinned memory — https://cloudcompute.ru/solutions/fp8-bf16/ и https://cloudcompute.ru/solutions/performance-tuning/.
  7. CI/CD: фиксируйте конфиги Δ/лимитов/версий — https://cloudcompute.ru/solutions/containers-ci-cd/.
  8. Хранилище: NVMe‑кэш и выгрузка в «тёплое/холодное» — https://cloudcompute.ru/solutions/storage-data/.
  9. Мульти‑GPU/роутинг: https://cloudcompute.ru/solutions/multi-gpu/.

Чек‑лист перед продом

  • Определены SLO: TTFT(p95), latency(p95), drop% для каждого класса трафика.
  • Настроены очереди/приоритеты и окно Δ; TTFT(p95) в бюджете.
  • GPU util 60–85%, VRAM запас ≥ 20%; нет I/O backlog.
  • Метрики и алерты подключены; есть дашборды очередей и latency.
  • Для LLM — раздельные очереди префилл/декод; для CV — ring‑buffer и drop‑политики.
  • Включены BF16/FP8 и KV‑dtype оптимизации (где безопасно).
  • Admission/rate limit защищают сервис; предусмотрены 503 с retry‑hint.
  • Параметры батчинга/лимитов зафиксированы в CI/CD.
  • Экономика подтверждена в https://cloudcompute.ru/solutions/cost-planner/.

Навигация