Решения
NVIDIA Triton: мультифреймворк‑сервинг на GPU
Задача страницы. Развернуть и эксплуатировать NVIDIA Triton на https://cloudcompute.ru для сервинга моделей PyTorch/ONNX/TensorRT/Python‑backend с динамическим батчингом, пайплайнами (Ensemble), приоритизацией трафика и прозрачной наблюдаемостью, не жертвуя SLO и экономикой.
TL;DR
- Triton объединяет разные фреймворки и форматы (TorchScript/ONNX/TensorRT/Python) в единый сервер с динамическим батчингом и Ensemble‑графами.
- Для онлайна (On‑Demand) — низкая латентность, короткое окно batching Δ, стриминг ответов (SSE/WebSocket), раздельные очереди по приоритетам на уровне шлюза. Для офлайна (Interruptible) — длинное Δ, крупные батчи, чанки ≤ 120 сек. См. https://cloudcompute.ru/solutions/interruptible-patterns/.
- Контролируйте баланс throughput vs latency: окно Δ, preferred_batch_size, instance_group, конкуррентность. См. https://cloudcompute.ru/solutions/throughput-vs-latency/.
- Выигрывайте в цене/производительности за счёт BF16/FP8/INT8 (где поддерживается), pinned/zero‑copy. См. https://cloudcompute.ru/solutions/fp8-bf16/ и https://cloudcompute.ru/solutions/performance-tuning/.
- Визуализируйте метрики p50/p95, очереди, GPU util/HBM, кэш‑хиты — см. https://cloudcompute.ru/solutions/monitoring-logging/ и https://cloudcompute.ru/solutions/llm-inference/observability/.
- Храните модели/артефакты на NVMe, разгружайте в «тёплое/холодное» — см. https://cloudcompute.ru/solutions/storage-data/.
- Масштабируйте по мульти‑GPU/мульти‑нод без cross‑GPU блокировок — см. https://cloudcompute.ru/solutions/multi-gpu/.
- Экономика: считайте Cost_per_query, Cost_per_1M_tokens/frames от c_gpu, целевой загрузки U, TPS/FPS — см. https://cloudcompute.ru/solutions/cost-planner/.
Сценарии
- LLM‑инференс: префилл/декод как отдельные модели/инстансы, микробатчинг, стриминг токенов.
- CV/видеоаналитика: батчирование кадров×камер, NVDEC→предобработка→инференс→постпроцесс.
- Классический ML‑скoring: ONNX/TensorRT для низкой латентности, Python‑backend для лёгкого препроцесса.
- Ensemble‑пайплайны: препроцесс→основная модель→постпроцесс как единый граф.
- A/B и канареечный релиз: две версии модели в одном репозитории, роутинг на уровне шлюза.
- Edge‑экспорт/общее хранилище моделей: единый репозиторий, промо через CI/CD.
Архитектуры/пайплайны

A) Онлайн LLM (низкая латентность)
Клиент → API Gateway (приоритеты, rate limit)
→ Triton: prefill_model (Δ_small, 1–2 инстанса/GPU)
→ Triton: decode_model (высокая конкуррентность)
→ SSE/WebSocket (стриминг токенов)
Метрики: TTFT, p95 latency, tokens/s, q_len_prefill/decode, gpu_util/hbm
B) CV пайплайн через Ensemble
RTSP → NVDEC → Preprocess(Python backend)
→ Detect(ONNX/TensorRT)
→ Postprocess(Python backend) → Event Bus/SSE
C) Офлайн‑батчи (высокий throughput, Interruptible)
Job Queue → N×Triton Executors (Docker)
├─ Δ_large batching
├─ локальный NVMe кэш
└─ выгрузка результатов в "тёплое/холодное"
Профили GPU / VRAM / ориентиры
Профиль | Видеопамять | LLM/текст | CV/видео | Мульти‑модель | Рекомендации |
24 ГБ (Compact) | 24 ГБ | малые/средние модели, короткий контекст | 1080p@30–60, 1–2 потока | 1–2 модели | Δ≤20–40 мс, 1 инстанс/модель, NVENC ≤2 |
48 ГБ (Balanced) | 48 ГБ | средние модели, несколько клиентов | 1080p@60, 2–3 потока | 2–4 модели | Δ≤40–80 мс, 2 инстанса/модель, batch 32–128 |
80 ГБ (HQ) | 80 ГБ | крупные модели/длинный контекст | 4K@30–45, 3–4 потока | 4–6 моделей | Δ≤80–120 мс, 2–3 инстанса, FP8/INT8 кэш |
Держите запас VRAM ≥ 20%. Для сложных пайплайнов разделяйте модели по инстансам/процессам.
Репозиторий моделей: структура
models/
bert/
1/model.onnx
config.pbtxt
detector/
1/model.plan # TensorRT
config.pbtxt
preprocess/
1/model.py # Python backend
config.pbtxt
postprocess/
1/model.py
config.pbtxt
cv_ensemble/
config.pbtxt # без папки версии — Ensemble как маршрут


Конфиги и скелеты
1) Docker Compose (Triton + модели + шлюз FastAPI)
version: "3.9"
services:
triton:
image: nvcr.io/nvidia/tritonserver:xx.yy-py3
runtime: nvidia
gpus: all
command: >
tritonserver
--model-repository=/models
--exit-on-error=false
--response-cache=true
--http-port=8000 --grpc-port=8001 --metrics-port=8002
environment:
- NVIDIA_VISIBLE_DEVICES=all
volumes:
- /data/nvme/models:/models:ro
- /data/nvme/cache:/cache
ports: ["8000:8000","8001:8001","8002:8002"]
networks: [serving]
gateway:
image: ghcr.io/your-org/fastapi-gateway:latest
environment:
- TRITON_HTTP=http://triton:8000
ports: ["8080:8080"]
networks: [serving]
networks:
serving: {}
2) ONNX‑модель: config.pbtxt (динамический батчинг)
name: "bert"
backend: "onnxruntime"
max_batch_size: 128
input [
{ name: "input_ids" data_type: TYPE_INT32 dims: [ -1 ] },
{ name: "attention_mask" data_type: TYPE_INT32 dims: [ -1 ] }
]
output [
{ name: "logits" data_type: TYPE_FP16 dims: [ -1 ] } # FP16 для экономии
]
dynamic_batching {
preferred_batch_size: [ 4, 8, 16, 32, 64 ]
max_queue_delay_microseconds: 60000 # Δ = 60 мс (онлайн)
}
instance_group [
{ kind: KIND_GPU, count: 1 }
]
response_cache { enable: true }
3) TensorRT‑модель: config.pbtxt (высокий throughput)
name: "detector"
platform: "tensorrt_plan"
max_batch_size: 256
input [
{ name: "images" data_type: TYPE_FP16 dims: [ 3, -1, -1 ] }
]
output [
{ name: "boxes" data_type: TYPE_FP16 dims: [ -1, 4 ] },
{ name: "scores" data_type: TYPE_FP16 dims: [ -1 ] },
{ name: "labels" data_type: TYPE_INT32 dims: [ -1 ] }
]
dynamic_batching {
preferred_batch_size: [ 8, 16, 32, 64, 128 ]
max_queue_delay_microseconds: 120000 # Δ = 120 мс (офлайн)
}
instance_group [
{ kind: KIND_GPU, count: 2 } # два инстанса на GPU
]
4) Python‑backend (препроцесс) preprocess/config.pbtxt
name: "preprocess"
backend: "python"
max_batch_size: 128
input [{ name: "image_bytes", data_type: TYPE_UINT8, dims: [ -1 ] }]
output [{ name: "images", data_type: TYPE_FP16, dims: [ 3, 640, 640 ] }]
# models/preprocess/1/model.py
import numpy as np
import triton_python_backend_utils as pb
class TritonPythonModel:
def initialize(self, args):
pass
def execute(self, requests):
responses = []
for req in requests:
inp = pb.get_input_tensor_by_name(req, "image_bytes")
bs = inp.as_numpy() # (batch, bytes)
imgs = []
for b in bs:
# ... декод JPEG/resize/normalize → (3,640,640) FP16
imgs.append(np.zeros((3,640,640), dtype=np.float16))
out = pb.Tensor("images", np.stack(imgs, axis=0))
responses.append(pb.InferenceResponse(output_tensors=[out]))
return responses
5) Ensemble (CV конвейер) cv_ensemble/config.pbtxt
name: "cv_ensemble"
platform: "ensemble"
max_batch_size: 128
input [{ name: "image_bytes", data_type: TYPE_UINT8, dims: [ -1 ] }]
output [
{ name: "boxes", data_type: TYPE_FP16, dims: [ -1, 4 ] },
{ name: "scores", data_type: TYPE_FP16, dims: [ -1 ] },
{ name: "labels", data_type: TYPE_INT32, dims: [ -1 ] }
]
ensemble_scheduling {
step [
{
model_name: "preprocess"
input_map { key: "image_bytes" value: "image_bytes" }
output_map { key: "images" value: "images" }
},
{
model_name: "detector"
input_map { key: "images" value: "images" }
output_map { key: "boxes" value: "boxes" }
output_map { key: "scores" value: "scores" }
output_map { key: "labels" value: "labels" }
}
]
}
6) Клиент FastAPI → Triton (HTTP) со стримингом SSE
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import tritonclient.http as http
import numpy as np, io
TRITON_URL = "http://localhost:8000"
cli = http.InferenceServerClient(url=TRITON_URL)
app = FastAPI()
@app.post("/detect")
def detect(image: bytes):
inputs = [http.InferInput("image_bytes", [1, len(image)], "UINT8")]
inputs[0].set_data_from_numpy(np.frombuffer(image, dtype=np.uint8).reshape(1, -1))
outputs = [http.InferRequestedOutput("boxes"),
http.InferRequestedOutput("scores"),
http.InferRequestedOutput("labels")]
res = cli.infer("cv_ensemble", inputs=inputs, outputs=outputs)
return {
"boxes": res.as_numpy("boxes").tolist(),
"scores": res.as_numpy("scores").tolist(),
"labels": res.as_numpy("labels").tolist(),
}
@app.get("/generate")
def generate(prompt: str):
def stream():
# пример: ранняя отдача токенов; сервер внутри батчит/декодит
for tok in llm_tokens_from_triton(prompt, delta_ms=20):
yield f"data: {tok}\n\n"
return StreamingResponse(stream(), media_type="text/event-stream")
Наблюдаемость, метрики, алерты
См. https://cloudcompute.ru/solutions/monitoring-logging/ и https://cloudcompute.ru/solutions/llm-inference/observability/.
Ключевые
- Очереди/батчинг: queue_delay_ms (p50/p95), batch_size_eff, inflight_requests.
- Латентность: ttft_ms (для LLM), end_to_end_ms (p50/p95), inter_token_ms.
- Throughput: qps, fps, tokens_s, prefill_tps/decode_tps.
- GPU: gpu_util_pct, gpu_mem_used_gb (HBM), sm_efficiency_pct, pcie_tx_mb_s.
- Кэш: response_cache_hit_ratio, model_repo_cache_hit_ratio.
- I/O: i/o_backlog_sec, nvme_read_mb_s, nvme_write_mb_s.
Алерты (примеры)
- ttft_ms(p95) > SLO → уменьшить Δ, увеличить инстансы модели/нод.
- queue_delay_ms ↑ и gpu_util_pct < 30% → узкое место вне GPU (I/O/CPU).
- gpu_mem_used_gb/vram > 0.9 → уменьшить batch/контекст или включить BF16/FP8/INT8 (см. https://cloudcompute.ru/solutions/fp8-bf16/).
- response_cache_hit_ratio < целевого при повторяющихся запросах → включить/расширить кэш/ttl.
Экономика и формулы
Обозначения: c_gpu — цена GPU/час; U — целевая загрузка GPU; Δ — окно batching; QPS — запросов/сек; TPS — токенов/сек; t_h — часы.
Цена за запрос
EffCostPerHour = c_gpu / U
ReqPerHour = QPS * 3600
Cost_per_query = EffCostPerHour / ReqPerHour
LLM токены
TokensPerHour = TPS * 3600
Cost_per_1000_tok = EffCostPerHour / (TokensPerHour / 1000)
Влияние Δ и батча
Latency ≈ queue_delay(Δ) + service_time(batch)
Throughput ↑ с ростом batch, но TTFT ↑ → ищите минимум Cost_per_query при TTFT(p95) ≤ SLO
Планирование — https://cloudcompute.ru/solutions/cost-planner/, компромиссы — https://cloudcompute.ru/solutions/throughput-vs-latency/.
Безопасность и политики
- Секреты/ключи: только в секрет‑хранилищах/переменных окружения контейнеров; не логируйте payload. См. https://cloudcompute.ru/solutions/security/.
- PII/ретеншн: для пользовательских данных — маскирование, ротация/архивация, раздельные среды. См. https://cloudcompute.ru/solutions/storage-data/.
- Изоляция трафика: классы приоритета (realtime/bulk) и лимиты; anti‑noisy‑neighbor.
- Сетевой периметр: ограничьте доступ к портам HTTP/gRPC/metrics, аудит вызовов.
- Прерываемость: офлайн‑джобы идемпотентны, чекпоинты ≤ 120 сек. См. https://cloudcompute.ru/solutions/interruptible-patterns/.
Траблшутинг
Симптом | Причина | Решение |
TTFT вырос, p95 деградирует | Δ слишком велик, смешение long/short запросов | Снизить Δ для префилла, сегментировать очереди, выделить инстансы под long‑контекст. |
Очередь растёт при низкой GPU util | Узкое место I/O/CPU, препроцесс в Python | Вынести препроцесс в TensorRT/ONNX, включить pinned/zero‑copy, увеличить vCPU/NVMe. |
OOM на больших батчах | KV/активации в FP16/BF16 | Снизить batch, включить INT8/FP8 (где доступно), ограничить контекст. См. /solutions/fp8-bf16/. |
«Пила» латентности | Агрессивный автоскейлинг | Ввести гистерезис, зафиксировать min/max инстансы, стабилизировать Δ. |
Не конвертируется модель | Несовместимые операторы/динамические размеры | Экспорт в другой формат (TorchScript/ONNX), статические размеры, разделение на препроц/инференс. |
Python‑backend тормозит | GIL/интерпретируемые циклы | Векторизовать, Numpy/CuPy, вынести в TensorRT/ONNX, распараллелить инстансы. |
503 на шлюзе | Admission защитил SLO | Увеличить capacity realtime‑класса, шардировать по нодам, включить кэш ответа. |
Падение точности при FP8/INT8 | Квантование критичных узлов | Исключить LN/Softmax/Logits из квантизации, калибровать amax. См. https://cloudcompute.ru/solutions/fp8-bf16/. |
Как запустить в cloudcompute.ru
- Выберите шаблон (Docker/SSH/Jupyter) на https://cloudcompute.ru/solutions/templates/.
- Подготовьте репозиторий моделей на NVMe: models/… как в примере, версионирование/манифест.
- Выберите профиль GPU: 24 ГБ (Compact) / 48 ГБ (Balanced) / 80 ГБ (HQ).
- Настройте dynamic batching (preferred_batch_size, max_queue_delay) по SLO, разделите онлайновые и офлайновые модели/инстансы. См. https://cloudcompute.ru/solutions/throughput-vs-latency/.
- Включите mixed precision/кэш (BF16/FP8/INT8, response cache) — см. https://cloudcompute.ru/solutions/fp8-bf16/.
- Подключите наблюдаемость и алерты — https://cloudcompute.ru/solutions/monitoring-logging/ и https://cloudcompute.ru/solutions/llm-inference/observability/.
- Для масштабирования — мульти‑GPU/мульти‑нод и роутер на шлюзе — https://cloudcompute.ru/solutions/multi-gpu/.
- Зафиксируйте конфиги в CI/CD и промоутируйте версии — https://cloudcompute.ru/solutions/containers-ci-cd/.
- Проверяйте экономику через https://cloudcompute.ru/solutions/cost-planner/.
Чек‑лист перед продом
- SLO: TTFT(p95), latency(p95), QPS/FPS/TPS определены и проверены.
- Δ и preferred_batch_size настроены, очереди стабильны, нет head‑of‑line blocking.
- GPU util 60–85%, запас VRAM ≥ 20%; I/O backlog отсутствует.
- Модели разнесены по инстансам/приоритетам; офлайн — в отдельный пул.
- Кэш ответов/моделей включён и даёт целевой hit‑ratio.
- Метрики/алерты/трейсы доступны; логи чисты от PII.
- Mixed precision (BF16/FP8/INT8) включена там, где качество не проседает.
- Репозиторий моделей версионирован; промо через CI/CD.
- Экономика подтверждена: Cost_per_query/Cost_per_1M_tokens в бюджете.
Навигация
- Хаб «Решения»: https://cloudcompute.ru/solutions/
- Шаблоны запусков: https://cloudcompute.ru/solutions/templates/
- Планирование стоимости: https://cloudcompute.ru/solutions/cost-planner/
- Тюнинг производительности: https://cloudcompute.ru/solutions/performance-tuning/
- FP8/BF16: https://cloudcompute.ru/solutions/fp8-bf16/
- Throughput vs Latency: https://cloudcompute.ru/solutions/throughput-vs-latency/
- Multi‑GPU/Multi‑node: https://cloudcompute.ru/solutions/multi-gpu/
- Хранилища и данные: https://cloudcompute.ru/solutions/storage-data/
- Наблюдаемость/логи: https://cloudcompute.ru/solutions/monitoring-logging/
- Observability для сервисов: https://cloudcompute.ru/solutions/llm-inference/observability/
- Gradio/FastAPI (стриминг UI): https://cloudcompute.ru/solutions/gradio-fastapi/
- Контейнеры и CI/CD: https://cloudcompute.ru/solutions/containers-ci-cd/