docs(perception): record latency and triton parity limits
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# Observatory: четыре этапа создания полного real-time Perception-профиля
|
||||
|
||||
Дата: 2026-09-01; обновлено 2026-09-02 01:50 МСК. Текущая цель — переносимые полные профили и снижение задержек всей цепочки; допустимый лабораторный overload не блокирует разработку и не выдаётся за real-time PASS. Искусственный `handoff-overflow` устранён без расширения общего лимита двух pending кадров: два повторных source-paced Worker-прогона полного графа дали 128/128 результатов и 0 drops. Source→local receiver p95 = 128.75/122.69 ms, p99 = 151.67/157.10 ms; zero-drop gate теперь проходит, совокупный 125 ms latency gate — нет. Этап 1 частично выполнен; этапы 2–4 не начаты. Static-obstacle слой и coarse `hard_surface` остаются достаточными для сельского прототипа; профиль не сводится к одной модели.
|
||||
Дата: 2026-09-01; обновлено 2026-09-02 02:47 МСК. Цель прежняя: переносимые полные профили и снижение задержек всей цепочки. Surface cache reuse подтверждён без изменения outputs; 12 новых source-paced проб дали 128/128 и 0 drops. Единственный latency PASS с cadence 50 ms не выдержал повтора. Экспериментальный unified Triton + native NumPy дал mean 75.03 ms, p95 116.76 ms, p99 137.58 ms — strict gate не закрыт. TensorRT дополнительно не принят по parity: одна ячейка grass→hard_surface изменила NO_GO→ALLOW_candidate. Default остаётся PyTorch. Этап 1 частично выполнен; этапы 2–4 не начаты. Допустимый лабораторный overload не равен real-time PASS; static-obstacle и coarse hard_surface остаются достаточным scope.
|
||||
|
||||
Последнее изменение, 2026-09-02 01:43–01:50 МСК: source commit `2945859` вводит точный synchronous rendezvous готового GPU-результата с уже ожидающим chronological CPU consumer. Такой результат не становится pending даже на микроскопический интервал; если consumer занят, прежняя buffered reservation и тот же drop-policy сохраняются. Повторы использовали 127–128 direct handoffs и 0–1 buffered handoff, peak pending=1, peak input bytes=5,202,376. Все обязательные outputs двух повторов совпали 128/128. Профиль остаётся observation-only, standalone release и внешний transport ещё не проверены.
|
||||
Последнее изменение, 2026-09-02 01:57–02:47 МСК: `d9ea7c1` убирает повторное группирование online cloud; добавлены NVML, source-clocked layer freshness, FP32 TensorRT-кандидат и точный NumPy preprocess без межпроцессного tensor round trip. На 128 K1-кадрах preprocess tensor совпадает побитово; TensorRT mask — нет (4,009 пикселей, 0.01195%). Полный граф выявил policy-эффект на одной ячейке, поэтому кандидат остаётся unqualified. CUDA Graphs и busy-wait не закрыли p99. Непрерывный component-test на реальном кадре ~2.67 ms против десятков ms source-paced server interval задаёт следующий разрез: GPU/host timeline и clocks, без преждевременного обвинения сети или 24 GiB VRAM. Профиль остаётся observation-only; standalone release и внешний transport не проверены.
|
||||
|
||||
Текущий evidence: [отчёт этапа 1](../experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md), [ADR 0049](adr/0049-stream-first-perception-profiles.md), [candidate manifest](../config/perception/k1-perception-ddrnet39-rfdetr-tgs-prototype-v1.json). Запрет full-source preload закреплён в новом контракте; старый batch materializer пока не удалён и продуктовый путь не переключён.
|
||||
|
||||
@@ -238,11 +238,16 @@ EoMT — семейство ViT-моделей сегментации изобр
|
||||
- 2026-09-02 01:33 МСК: временно остановленные Triton, perception Worker и два Observatory agent возвращены в исходное состояние; Triton healthy/ready=200, оба agent running, canonical Mac 8000=200, Mac 8765 закрыт. Legacy perception Worker возобновил существовавший до замера HTTP 404 restart loop (running, restart count 4 на контрольном снимке); новый пилот от него не зависел. Ollama/Frigate сохранены exited/restart=no. Модельные запуски были строго последовательными; EoMT и посторонняя GPU-нагрузка не запускались.
|
||||
- 2026-09-02 01:43–01:50 МСК: `2945859` заменил ложную buffered reservation на synchronous rendezvous, только когда consumer уже ждёт. 109 focused tests и Ruff PASS. Два последовательных Worker-повтора: 128/128, 0 drops, unaccounted=0; p95 = 128.75/122.69 ms, p99 = 151.67/157.10 ms. Повторная функциональная parity всех 128 outputs PASS. Evidence: `.runtime/perception-handoff-worker-20260902T0143MSK/manifest.json`, SHA-256 `d68af383c42eb3686ef199afeebd4625f27d573b77109e7e8ff8c85e811a9003`.
|
||||
- 2026-09-02 01:50 МСК: Worker-сервисы снова возвращены в исходное состояние; Triton healthy/ready=200, оба Observatory agent running, active pilot containers=0, canonical Mac 8000=200, Mac 8765 закрыт. Legacy perception Worker возвращён в прежнюю HTTP 404 restart-loop конфигурацию; Ollama/Frigate exited/restart=no.
|
||||
- Этап 1: частично выполнен; функциональный общий граф, исправленный preroll и bounded handoff измерены, zero-drop gate на двух повторах закрыт. Real-time qualification не закрыта из-за p99 >125 ms, а standalone/network transport ещё отсутствуют. Следующие задачи: довести выходной layered-freshness ABI, перенести расписание в общий runtime и профилировать DDRNet/CPU tail, затем измерить transport/application boundary. Нельзя закрывать whole-path gate по compute-only метрике.
|
||||
- 2026-09-02 01:57–02:47 МСК: surface reuse `d9ea7c1` сохранил functional parity 128/128, surface p99 19.44/21.87 ms. NVML/no-telemetry и cadence 50/100 ms не дали повторяемого latency PASS. Unified Triton с DDRNet/RF-DETR исполняет модели последовательно; NumPy preprocessing точен 128/128, но TensorRT mask отличается на 0.01195% пикселей и меняет одну ячейку grass→hard_surface / NO_GO→ALLOW_candidate. Backend не продвинут в default. Измерены пять whole-graph Triton variants, p99 137.58–151.37 ms; CUDA Graph/busy-wait проблему не закрыли. 119 focused tests PASS. Evidence: `.runtime/perception-unified-triton-worker-20260902T0227MSK/manifest.json`, SHA-256 `ed81475e71b7d02af03dbc65ef628065baaec80bf4877b83e80cc6b3d682a330`.
|
||||
- 2026-09-02 02:47 МСК: pilot containers=0, Triton healthy, два Observatory agent running, local 8000=200, 8765 закрыт. Legacy perception Worker восстановлен в прежнюю HTTP404 restart-loop конфигурацию; Ollama/Frigate exited/restart=no. Нет product cutover/deployment, raw/weights/runtime не добавлены в Git.
|
||||
- Git checkpoint: `d9ea7c1` — surface cache reuse; `34f13ba` — bounded Triton/cadence/NVML/preprocess diagnostics и regression tests. Документы и выводы фиксируются отдельно; push не выполнялся.
|
||||
- Этап 1: частично выполнен. Следующие задачи: согласовать TensorRT numeric/material parity до его продвижения, измерить GPU clocks и GPU/host timeline при source-paced паузах, довести выходной layered-freshness ABI и общий runtime; затем application↔Worker streaming transport. Нельзя закрывать whole-path gate по повторению одного tensor или принимать малый pixel mismatch без проверки policy.
|
||||
- Этапы 2, 3, 4: не начаты. Продуктовый backend/frontend path, active registry, canonical local 8000 и физический источник не переключались. Старый full-source materializer остаётся legacy; новый streaming transport ещё не реализован.
|
||||
|
||||
## Surprises / открытые вопросы
|
||||
|
||||
- Малое численное расхождение backend не обязательно семантически безвредно: 0.01195% DDRNet pixel mismatch изменили material/policy одной ячейки. Без ground truth нельзя назвать один backend правильным; без parity нельзя заменить reference автоматически.
|
||||
- Triton server `compute_infer` interval не тождественен CUDA kernel time. Точный реальный frame в непрерывном trtexec дал mean 2.67 ms, тогда как source-paced Triton — 23.61 ms server interval. Clocks/driver/event scheduling ещё не разделены; смена HTTP на gRPC или покупка GPU пока не являются доказанным исправлением.
|
||||
- Глобальная блокировка очереди противоречит независимости будущих Worker; нужно перенести ownership scope, а не просто оставить `max_concurrency=1` во всех слоях.
|
||||
- Старые combined-package manifests сохраняют batch-семантику и не исполняют detector/geometry/TGS/threat. Красивый общий viewer использует отдельные сохранённые результаты; это не готовый профиль.
|
||||
- FPS исходного recording и старые sampling/min-FPS требования математически расходятся. Численные product budgets должны быть закрыты в этапе 1; пользователь не задал их в этом уточнении.
|
||||
@@ -276,6 +281,6 @@ EoMT — семейство ViT-моделей сегментации изобр
|
||||
|
||||
## Outcomes / retrospective
|
||||
|
||||
Результат этапа 1 на текущий момент: исполняемые invariants, pinned manifest-кандидат, component baseline и измеренный совместный граф с bounded causal history, очередью и исходным 1× clock. Исправленный preroll и прямой handoff функционально подтверждены на Worker; два последних повтора дали 128/128 без drops, но p99 остался выше 125 ms. Transport, network end-to-end, переносимость по нескольким записям и standalone packaging остаются непроверенными. Экспорт image дополнительно упёрся в отсутствующий cached Triton blob / NVCR 403; временный mounted pilot не заменяет поставляемый образ. Ollama/Frigate остались выключенными, остальной временно остановленный Mission Core-контур возвращён в исходное состояние.
|
||||
Результат этапа 1 на текущий момент: исполняемые invariants, pinned manifest-кандидат, component baseline и полный граф с bounded causal history/queue и исходным 1× clock. Preroll, direct handoff и surface reuse функционально подтверждены. Добавлены измерения слоёв и экспериментальный unified Triton path; 128-frame NumPy tensor parity точна, но TensorRT material/policy parity не пройдена и default не изменён. Все 12 последних проб zero-drop, стабильного 125 ms gate нет. Source-paced server/GPU gap локализован, причина ещё требует GPU/host timeline. Network end-to-end, несколько записей и standalone packaging остаются непроверенными; прежний cached Triton blob / NVCR403 blocker не перепроверялся. Mounted pilot не заменяет поставляемый образ. Ollama/Frigate выключены, остальные временно остановленные сервисы возвращены в исходное состояние.
|
||||
|
||||
После этапа 4 здесь будут перечислены digest самостоятельного полного образа, измеренные статусы и ошибки по recordings, реально проверенные source/hardware/config комбинации, состояние сохранённого EoMT-варианта и оставшиеся physical-live/quality/vehicle-integration ограничения. Готовый Docker и готовая автономия не отождествляются.
|
||||
|
||||
@@ -15,6 +15,14 @@ latency runs; shared-budget CPU overlap дважды дал 128/128 без drops
|
||||
p95 128.75/122.69 ms и p99 151.67/157.10 ms. Это не product cutover,
|
||||
не самостоятельный образ и пока не latency qualification.
|
||||
|
||||
Последнее дополнение — 2026-09-02 02:47 МСК: surface cache reuse подтверждён
|
||||
без изменения functional outputs; добавлены NVML, source-clocked layer freshness
|
||||
и экспериментальный DDRNet TensorRT backend в общем Triton с RF-DETR.
|
||||
Все 12 новых source-paced запусков дали 128/128 без drops, но стабильного
|
||||
125 ms gate нет. TensorRT-кандидат дополнительно **не принят по parity**:
|
||||
0.01195% отличающихся пикселей изменили одну ячейку grass→hard_surface и
|
||||
NO_GO→ALLOW_candidate. Default остаётся pinned PyTorch; подробности в конце.
|
||||
|
||||
## Решение и сделанный объём
|
||||
|
||||
Первый профиль зафиксирован как `K1 Perception — DDRNet-39 + RF-DETR + TGS`:
|
||||
@@ -711,3 +719,148 @@ Ollama/Frigate остаются exited/restart=no. Deployment и product cutover
|
||||
**Следующий открытый риск этапа 1:** output-level layered freshness и latency
|
||||
tail. Direct handoff можно переносить в общий runtime; p99 требует отдельного
|
||||
профилирования DDRNet/CPU sections и затем повторного whole-path gate.
|
||||
|
||||
## Surface / telemetry / cadence / unified Triton — 2026-09-02 01:57–02:47 МСК
|
||||
|
||||
### Принятые изменения и сохранённая граница
|
||||
|
||||
Commit `d9ea7c1` переиспользует уже вычисленные cell observations в online
|
||||
local-surface cache вместо второго группирования того же облака. Оба
|
||||
128-frame Worker-повтора побитово сохраняют segmentation/proposals,
|
||||
lineage/binding, observations, tracks, threats, range/surface state,
|
||||
costmap states/material и non-timing TGS. Surface p99 = 19.44 / 21.87 ms.
|
||||
Runtime age/stale flags не входят в побитовое сравнение вычислений.
|
||||
|
||||
Новая NVML-сессия заменяет запуск `nvidia-smi` каждые 500 ms. Контроль без
|
||||
телеметрии не убрал хвост: это полезное упрощение наблюдателя, не доказанное
|
||||
решение p99. `none` применяется только для диагностики и честно оставляет
|
||||
resource gates непроверенными.
|
||||
|
||||
Пилот теперь публикует source sequence/time, source age и age-at-policy
|
||||
для segmentation/detection/geometry. Экспериментальный DDRNet cadence
|
||||
определяется исходным временем, detector и CPU graph продолжают каждый кадр;
|
||||
повторно используемая маска не получает новый timestamp. `interval=0` остаётся
|
||||
default. 50 ms cadence использовал 118 новых масок и 10 явно reused;
|
||||
100 ms — 82/46. Один удачный 50 ms запуск не выдержал повтора, поэтому
|
||||
снижение cadence не принято как способ закрыть latency gate. Это ещё не
|
||||
полный versioned layered-freshness ABI общего продуктового runtime.
|
||||
|
||||
### Все результаты, включая отрицательные
|
||||
|
||||
Источник и временное окно прежние; все 12 запусков: 128 released,
|
||||
128 completed, 0 drops/unaccounted, clock=1×, capacity=2, byte limit=16 MiB.
|
||||
Модели и профили не считались параллельно. Числа ниже — source due→local
|
||||
receiver, не только inference и не сеть приложение↔Worker.
|
||||
|
||||
| Run | Mean, ms | p95, ms | p99, ms | 125 ms latency gate |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| surface-cache A | 82.42 | 120.32 | 134.60 | FAIL |
|
||||
| surface-cache B | 74.79 | 118.94 | 153.58 | FAIL |
|
||||
| NVML surface | 75.26 | 125.43 | 181.81 | FAIL |
|
||||
| без telemetry, diagnostic | 79.04 | 116.55 | 160.31 | FAIL |
|
||||
| DDRNet interval 50 ms A | 71.93 | 105.19 | 119.18 | PASS только этого окна |
|
||||
| DDRNet interval 50 ms B | 83.24 | 133.83 | 139.96 | FAIL повторения |
|
||||
| DDRNet interval 100 ms | 67.02 | 121.52 | 133.27 | FAIL |
|
||||
| unified Triton / pinned child A | 87.66 | 141.97 | 147.53 | FAIL |
|
||||
| unified Triton / pinned child B | 83.93 | 133.58 | 151.37 | FAIL |
|
||||
| unified Triton / native NumPy C | 75.03 | 116.76 | 137.58 | FAIL |
|
||||
| C + DDRNet CUDA Graphs D | 72.91 | 127.39 | 143.12 | FAIL |
|
||||
| D + busy-wait events E | 73.42 | 118.41 | 138.19 | FAIL |
|
||||
|
||||
### TensorRT: runtime-кандидат, не незаметная замена модели
|
||||
|
||||
Pinned DDRNet checkpoint экспортирован в FP32 ONNX и TensorRT 11 с
|
||||
`--noTF32`, без FP16/INT8. Sigmoid→first-index argmax→uint8 mask включён в
|
||||
engine: обратно приходит 256 KiB mask, а не 64 MiB logits. DDRNet и RF-DETR
|
||||
загружаются в один Triton process и исполняются строго последовательно.
|
||||
Это всё ещё тот же полный граф с online LiDAR/distance/motion/TGS/costmap/policy,
|
||||
не новая LAB-микропрограмма и не standalone release.
|
||||
|
||||
System Python 3.12 в базе не имел PIL/cv2, поэтому сначала точный preprocess
|
||||
работал в CPU-only Python 3.9 child. Затем fixed KB4 crop/nearest/RGB/255
|
||||
перенесён в NumPy текущего процесса. Проверка против pinned runner на всех
|
||||
128 реальных кадрах: **128/128 tensor побитово равны**, общий SHA-256
|
||||
`a01e97fa342e0b98b233a8fb4485108243406e89a171e1e8513f8b6d1f2f0e63`.
|
||||
Устранены передача 1,440,000 B BGR в child и 3,145,728 B tensor обратно;
|
||||
CPU decode child сохранён. Внутренний HTTP к Triton пока остаётся.
|
||||
|
||||
Однако PyTorch→TensorRT mask parity не пройдена: 4,009 различий из
|
||||
33,554,432 пикселей (0.01195%), ни один из 128 кадров не побитово равен.
|
||||
Functional сравнение выявило **одну смысловую разницу**: sequence 115,
|
||||
cell index 1900 / grid (15, −2), XY≈(6.975, −0.675) m:
|
||||
`grass → hard_surface`, `NO_GO → ALLOW_candidate`; обе сцены fresh.
|
||||
Это не timing/stale-эффект и не NumPy-препроцессинг. Между всеми пятью
|
||||
TensorRT-вариантами masks/material совпадают 128/128. Detector proposals,
|
||||
metric observations, tracks, threats, geometry/costmap occupancy и non-timing
|
||||
TGS совпадают с PyTorch на всех 128 кадрах.
|
||||
|
||||
**Решение:** TensorRT остаётся `experimental-unqualified`; default — PyTorch.
|
||||
Нельзя принять малый pixel mismatch как разрешение ослабить policy.
|
||||
Ground truth для спорной ячейки здесь не установлена: это доказанное
|
||||
расхождение, а не доказательство, какая модель права. Во всех запусках
|
||||
commands/actuation=false; stale scenes не выдают разрешающих actions.
|
||||
76/128 cloud/pose pairs доступны, 52 unavailable — это ограничение данного
|
||||
источника/контракта не исчезает от ускорения сегментации.
|
||||
|
||||
### Где осталась задержка
|
||||
|
||||
В C server statistics, исключая warmup: DDRNet server success mean 25.82 ms,
|
||||
из них `compute_infer` interval 23.61 ms, input/output 1.31/0.80 ms,
|
||||
server queue 0.074 ms. HTTP wall mean 28.30 ms. RF-DETR server
|
||||
`compute_infer` mean 7.51 ms. Эти server intervals — не CUDA-event
|
||||
доказательство чистого времени GPU kernels.
|
||||
|
||||
Отдельный bounded `trtexec` на точном реальном frame 0, 64 непрерывных
|
||||
повтора, CUDA Graph + spin wait, **без DMA и source pacing**:
|
||||
GPU mean 2.67048 ms, p99 3.43756 ms; ArgMax ~0.2152 ms.
|
||||
Синтетический repeated-input контроль дал ~2.65254 ms. Это исключает
|
||||
основание немедленно переписывать ArgMax, но не квалифицирует потоковый
|
||||
профиль и не даёт права обещать сотни FPS полного графа.
|
||||
|
||||
Следующий диагностический шаг — GPU clocks/power state и CUDA/host timeline
|
||||
при source-paced паузах, с разделением server/driver/event waits и actual
|
||||
kernel work. WDDM/context switching — гипотезы, не установленная единственная
|
||||
причина. Утверждения «всё из-за сети» и «4090 упёрлась в 24 GiB» не подтверждены:
|
||||
unified runs sampled VRAM peak 1,856–1,862 MiB; внешний сетевой участок не измерен.
|
||||
CUDA Graphs и busy-wait в Triton по отдельным полным пробам p99 не закрыли.
|
||||
Официальные измерительные определения:
|
||||
[Triton statistics](https://raw.githubusercontent.com/triton-inference-server/server/r26.06/docs/protocol/extension_statistics.md),
|
||||
[CUDA optimization config](https://raw.githubusercontent.com/triton-inference-server/common/r26.06/protobuf/model_config.proto).
|
||||
|
||||
### Evidence, проверки и состояние
|
||||
|
||||
Единый redacted manifest со всеми 12 результатами, hashes, parity и точными
|
||||
командами C/D/E:
|
||||
`.runtime/perception-unified-triton-worker-20260902T0227MSK/manifest.json`,
|
||||
SHA-256 `ed81475e71b7d02af03dbc65ef628065baaec80bf4877b83e80cc6b3d682a330`.
|
||||
Копия на Worker — одноимённый каталог под
|
||||
`D:/NDC_MISSIONCORE/runtime/experiments/`. Предыдущие surface/NVML/layered
|
||||
каталоги сохранены и перечислены в manifest; данные/веса не входят в Git.
|
||||
|
||||
| Артефакт | SHA-256 |
|
||||
| --- | --- |
|
||||
| unified probe v1 | `3e6d04fd8d2204933320a1b427ee1bebf4152a781fcc0bd2d6fe0d46e00244af` |
|
||||
| unified probe v2 | `f5225cccd8b164346aea780c0d5960f8114bffc5535d7bc1b55a4f84f54457a8` |
|
||||
| DDRNet mask ONNX | `595e40442f6829ee56618c88649f2024e56f469bc67a0768f0dda6cfd3fd82e4` |
|
||||
| DDRNet mask TensorRT plan | `e004e5cdd3daa14628fe52c5bd5418237e24a6423dddde56f82b402fbe536c3b` |
|
||||
|
||||
119 focused tests и Ruff изменённых файлов PASS; `git diff --check` PASS.
|
||||
Исходники диагностического runtime/export/parity и тесты зафиксированы
|
||||
отдельным commit `34f13ba`; surface optimization — `d9ea7c1`. Push не выполнялся.
|
||||
Финальные bounded-response checks и явная backend-status метка добавлены
|
||||
после Worker v2 и проверены локально; они не выдаются за измеренный v2 source.
|
||||
Full backend/frontend suite/build и model stress на Mac не выполнялись.
|
||||
Setup-запуски с отсутствующим cv2/PIL не вошли в performance. В первом
|
||||
unified A был лишний неиспользуемый readonly bind; B и последующие его не имели.
|
||||
|
||||
После окна pilot containers=0, штатный Triton running/healthy, оба Observatory
|
||||
agent running, canonical Mac 8000=200, 8765 закрыт. Legacy perception Worker
|
||||
вернулся в прежнюю конфигурацию с HTTP 404 restart loop (restart count 2 на
|
||||
контрольном снимке); эта посторонняя неисправность не объявлена исправленной.
|
||||
Ollama/Frigate остаются exited/restart=no. Product registry/defaults,
|
||||
внешний transport, standalone image и motor boundary не переключались.
|
||||
|
||||
**Вердикт:** этап 1 частичный. Функциональная оптимизация surface принята,
|
||||
реальный лишний IPC устранён в экспериментальном Triton path, предел лучше
|
||||
локализован. Стабильный whole-path latency, TensorRT parity, полный freshness
|
||||
ABI и standalone/network qualification остаются открытыми.
|
||||
|
||||
Reference in New Issue
Block a user