Экспорт моделей для edge: ONNX и TensorRT
Задача страницы. Пошагово показать, как из обученной CV‑модели получить лёгкий и быстрый edge‑пакет (ONNX → TensorRT), не потеряв качество: аудит препроц/постпроц, экспорт в ONNX с динамическими формами, сборка TensorRT‑движка в FP16/INT8, валидация точности/латентности, упаковка в контейнер, телеметрия и безопасные обновления.
TL;DR
- Зафиксируйте препроц/постпроц (resize/letterbox, нормализация, NMS/декод боксов) и версии весов до экспорта.
- Экспортируйте в ONNX (explicit batch, динамические формы) → проверьте точность на контрольном наборе → соберите TensorRT (FP16, затем INT8 с калибрацией).
- В проде для edge: один контейнер = один движок + единый препроц, наблюдаемость p50/p95, A/B‑обновления и откат.
- Смежные разделы: детекция — https://cloudcompute.ru/solutions/computer-vision/yolo/ • сегментация ROI — https://cloudcompute.ru/solutions/computer-vision/sam/ • тюнинг — https://cloudcompute.ru/solutions/performance-tuning/ • форматы BF16/FP16/FP8 — https://cloudcompute.ru/solutions/fp8-bf16/ • баланс latency↔throughput — https://cloudcompute.ru/solutions/throughput-vs-latency/ • сервинг/ансамбли — https://cloudcompute.ru/solutions/triton-inference-server/ • наблюдаемость — https://cloudcompute.ru/solutions/monitoring-logging/ и https://cloudcompute.ru/solutions/llm-inference/observability/ • CI/CD — https://cloudcompute.ru/solutions/containers-ci-cd/ • шаблоны запусков — https://cloudcompute.ru/solutions/templates/
Когда нужен edge‑экспорт
- Видео «на месте»: камеры/роботы/АТС, когда трафик дорог или приватность критична.
- AR/мобильные сценарии: малая латентность, ограниченный бюджет GPU/энергии.
- Полевые датчики: работа офлайн, периодическая синхронизация.
- Фильтрация у источника: предварительное отсечение событий перед отправкой в облако.
Аудит модели перед экспортом
- Зафиксируйте препроц: resize + letterbox, порядок каналов, нормализацию, типы (uint8→fp16).
- Зафиксируйте постпроц: декод якорей/боксов, NMS (класс‑wise/общий), top‑K, пороги.
- Уберите недетерминизм (случайные аугментации, dropout).
- Задокументируйте входы/выходы и динамические формы (H×W, N).
- Сделайте контрольный набор (200–1000 изображений) для сверки метрик после экспорта.
См. основы детекции/параметры NMS — https://cloudcompute.ru/solutions/computer-vision/yolo/ • тюнинг производительности — https://cloudcompute.ru/solutions/performance-tuning/
Экспорт в ONNX (динамические формы) Рекомендации
- Экспортируйте с explicit batch и динамикой по N,H,W.
- Выделите постпроц в отдельный узел: либо экспортируйте NMS в графе, либо оставьте NMS на хосте/плагине при сборке TensorRT.
- Используйте opset ≥ 13; проверьте, что все кастом‑операции заменены на стандартные (или опишите плагины).
Пример (PyTorch → ONNX, схематично):
import torch
model = load_trained_model().eval().half() # fp16 для совместимости с FP16 сборкой
dummy = torch.randn(1, 3, 640, 640).half().cuda()
dynamic_axes = {"images": {0: "N", 2: "H", 3: "W"},
"pred": {0: "N"}}
torch.onnx.export(
model, dummy, "model_edge.onnx",
input_names=["images"], output_names=["pred"],
opset_version=17, do_constant_folding=True,
dynamic_axes=dynamic_axes
)
Проверка эквивалентности: прогоните ONNX на контрольном наборе и сравните mAP/IoU/Recall. Разница в пределах 0.1–0.5 п.п. обычно допустима; больше — ищите несоответствие препроц/постпроц.
Сборка TensorRT‑движка
Шаги
- Выберите precision: FP16 → INT8 (после калибровки).
- Включите тактики оптимизации (workspace) и плагины для NMS/декода при необходимости.
- Задайте профили динамических форм (минимум/оптимум/максимум).
- Сохраните .engine и версионируйте вместе с метаданными (см. ниже).
Схема на Python (сокращённо):
import tensorrt as trt
builder = trt.Builder(trt.Logger(trt.Logger.INFO))
network = builder.create_network(1 << int(trt.NetworkDefinitionCreationFlag.EXPLICIT_BATCH))
parser = trt.OnnxParser(network, builder.logger)
with open("model_edge.onnx", "rb") as f:
parser.parse(f.read())
config = builder.create_builder_config()
config.set_memory_pool_limit(trt.MemoryPoolType.WORKSPACE, 2<<30) # 2GB
config.set_flag(trt.BuilderFlag.FP16)
# Профили динамических форм
profile = builder.create_optimization_profile()
profile.set_shape("images", min=(1,3,480,480), opt=(1,3,640,640), max=(4,3,1280,1280))
config.add_optimization_profile(profile)
# (опц.) INT8 калибратор
# config.set_flag(trt.BuilderFlag.INT8); config.int8_calibrator = MyCalibrator(...)
engine = builder.build_engine(network, config)
with open("model_edge_fp16.engine", "wb") as f:
f.write(engine.serialize())
INT8‑калибрация
- 300–1000 репрезентативных изображений препроцить ровно так же, как в проде.
- Лучше per‑channel для свёрток, исключить “хрупкие” слои из INT8, если качество падает.
- Сравните метрики до/после; откатитесь к FP16, если потеря качества недопустима.
Подробности о форматах вычислений — https://cloudcompute.ru/solutions/fp8-bf16/
Профили устройств и ожидания
| **Класс устройства** | **Память** | **Режимы** | **Заметки** |
| **Микро‑edge (iGPU/мобильные dGPU)** | 4–8 ГБ | FP16, реже INT8 | Одномодельные пайплайны, жёсткие лимиты тепла/энергии |
| **Jetson/«корневые» edge‑узлы** | 8–32 ГБ | FP16/INT8 | 1–3 модели, декод+инференс, лёгкий overlay |
| **Малые коробки с dGPU** | 8–24 ГБ | FP16/INT8 | Мультикамерные пайплайны, батч из потоков |
| **Near‑edge в ЦОД** | 24–80 ГБ | BF16/FP16/INT8 | Консолидация сайтов, многомодельные графы |
Баланс latency↔throughput — https://cloudcompute.ru/solutions/throughput-vs-latency/ Препроц/постпроц: как не «уронить» качество
- Letterbox: одинаковая реализация в train/export/edge.
- Нормализация: одинаковые mean/std, порядок каналов.
- NMS: одинаковые iou/conf, единая схема (class‑wise vs unified), top‑K и лимиты.
- Декод боксов: строго те же формулы (якоря/stride).
- Проверка: прогон контрольного набора в три режима — PyTorch, ONNX, TensorRT.
Параллелизм и конвейер
- Zero‑copy кадра в GPU, pinned memory для входов/выходов.
- Несколько CUDA‑стримов: decode → preprocess → infer → postproc с перекрытием.
- Микробатч для изображений 2–8, если это не бьёт по p95.
- Мультимодельные графы (например, детекция → классификация ROI) упаковываются как ансамбль — см. https://cloudcompute.ru/solutions/triton-inference-server/
Упаковка, версии и обновления (edge‑CI/CD)
- Образ контейнера: model.engine + конфиг препроц/постпроц + точные версии CUDA/TensorRT.
- Манифест (JSON): model_id, arch, preproc_hash, postproc_hash, trt_version, calib_digest, shapes_profile.
- A/B‑раскатка и быстрый откат при деградации.
- OTA‑обновления через пайплайн — см. https://cloudcompute.ru/solutions/containers-ci-cd/
Наблюдаемость на устройстве
Собирайте (см. https://cloudcompute.ru/solutions/monitoring-logging/ и https://cloudcompute.ru/solutions/llm-inference/observability/):
- Latency p50/p95, QPS/FPS, drop‑rate, очередь ожидания.
- GPU: util/HBM, VRAM пик, тепловой троттлинг.
- Качество: mAP/IoU по контрольным кадрам, доля пустых/переполненных выходов.
- События: ошибки десериализации .engine, несовпадение форм ввода, таймауты.
Экономика и sizing для edge‑пула
Пусть t_inf — время инференса на движке (сек), α — накладные препроц/постпроц/декода, fps — целевой FPS/поток, U — целевая загрузка GPU (например, 0.7).
t_frame ≈ t_inf + α
Max_streams_per_gpu ≈ (1 / (t_frame × fps)) × U
Для корневых узлов (несколько камер): суммируйте потоки и проверяйте пиковое потребление VRAM (движок + кэш + буферы). Планирование — https://cloudcompute.ru/solutions/cost-planner/
Конфиги (YAML): export→engine→runtime
A)Export (PyTorch→ONNX)
export:
input: checkpoints/yolo_s_best.pt
onnx_out: artifacts/yolo_s_dyn.onnx
opset: 17
dynamic: { N: [1, 4], H: [480, 1280], W: [480, 1280] }
postproc: separate # nms/decode вынесены наружу
preprocess:
letterbox: { enabled: true, fill: 114 }
normalize: { mean: [0.485,0.456,0.406], std: [0.229,0.224,0.225] }
B)Build (ONNX→TensorRT)
tensorrt:
onnx: artifacts/yolo_s_dyn.onnx
engine: artifacts/yolo_s_fp16.engine
precision: fp16 # fp16 | int8
workspace_gb: 2
profiles:
- name: p1
min: [1,3,480,480]
opt: [1,3,640,640]
max: [4,3,1280,1280]
int8:
calibrate: false
cache: artifacts/calib.cache
images_dir: calib_samples/
C) Runtime (edge‑контейнер)
runtime:
engine: /opt/models/yolo_s_fp16.engine
inputs: { name: images, dtype: fp16, nchw: true }
outputs: { name: pred, dtype: fp16 }
nms:
kind: batched
iou: 0.6
conf: 0.35
topk: 300
streams: 3
batch: 1
limits:
max_res: [1280,1280]
timeout_ms: 100
observability:
metrics: prometheus
traces: otlp
Траблшутинг
| **Симптом** | **Причина** | **Что сделать** |
| Падение mAP после экспорта | Несовпадение препроц/постпроц | Проверить letterbox/нормализацию/NMS, синхронизировать пороги |
| Ошибка десериализации .engine | Версия TensorRT/арх несовместима | Пересобрать движок под целевое устройство/версию |
| OOM/вылеты при старте | Неверный профиль форм/большие буферы | Уменьшить max‑формы, снизить workspace, проверить batch |
| INT8 ухудшил качество | Неполная/нерепрезентативная калибровка | Увеличить выборку, исключить хрупкие слои из INT8, вернуться на FP16 |
| Задержки «скачут» | Декод/копии, отсутствие стримов | NVDEC/zero‑copy, pinned memory, 2–4 CUDA‑стрима |
| Разные результаты на устройствах | Разные версии/seed | Зафиксировать версии библиотек, один манифест/контейнер |
Как запустить в cloudcompute.ru
Хаб шаблонов — https://cloudcompute.ru/solutions/templates/
- “Edge‑Export (ONNX→TensorRT)” — экспорт, сборка профилей форм, валидация метрик, упаковка контейнера.
- “CV‑Realtime (RTSP)” — конвейер decode→infer→postproc с низкой латентностью: https://cloudcompute.ru/solutions/computer-vision/video-analytics/
- “Triton‑Ensemble (CV)” — препроц→модель→NMS/NLP постпроц в одном сервинге: https://cloudcompute.ru/solutions/triton-inference-server/ Операции/обновления: https://cloudcompute.ru/solutions/containers-ci-cd/ • метрики/алерты: https://cloudcompute.ru/solutions/monitoring-logging/ • трассировка: https://cloudcompute.ru/solutions/llm-inference/observability/
Чек‑лист перед продом
- Зафиксированы препроц/постпроц, версии весов и контрольный набор.
- Экспорт ONNX с динамическими формами; проверена эквивалентность метрик.
- Собран TensorRT FP16; протестирован INT8‑движок (если нужен) и калибровка.
- Задан профиль форм (min/opt/max), протестированы реальные разрешения.
- Упакован контейнер с манифестом версий и limits; настроена A/B‑раскатка.
- Подключены метрики/трейсы/алерты; подтверждён SLA p95.
- Рассчитан Max_streams_per_gpu и проверен VRAM пик на устройстве.
Навигация по разделу «Компьютерное зрение»
Хаб: https://cloudcompute.ru/solutions/computer-vision/ • Детекция: https://cloudcompute.ru/solutions/computer-vision/yolo/ • Интерактивная сегментация: https://cloudcompute.ru/solutions/computer-vision/sam/ • Видео‑аналитика: https://cloudcompute.ru/solutions/computer-vision/video-analytics/ • Трекинг/ReID: https://cloudcompute.ru/solutions/computer-vision/tracking/ • OCR: https://cloudcompute.ru/solutions/computer-vision/ocr/ • Эмбеддинги: https://cloudcompute.ru/solutions/computer-vision/dinov2/ • Экспорт на edge (эта страница) • Инфраструктура/тюнинг/наблюдаемость/экономика: https://cloudcompute.ru/solutions/performance-tuning/ • https://cloudcompute.ru/solutions/fp8-bf16/ • https://cloudcompute.ru/solutions/monitoring-logging/ • https://cloudcompute.ru/solutions/llm-inference/observability/ • https://cloudcompute.ru/solutions/throughput-vs-latency/ • https://cloudcompute.ru/solutions/cost-planner/ • Шаблоны и CI/CD: https://cloudcompute.ru/solutions/templates/ • https://cloudcompute.ru/solutions/containers-ci-cd/
Готовы запустить?
Запустить GPU-сервер