From ce09d30c1a418c25f6cf10e5e91746bdd511d39a Mon Sep 17 00:00:00 2001 From: DCCONSTRUCTIONS Date: Wed, 2 Sep 2026 02:52:38 +0300 Subject: [PATCH] docs(perception): record latency and triton parity limits --- .../OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md | 13 +- .../PERCEPTION_STREAM_STAGE1_2026-09-01.md | 153 ++++++++++++++++++ 2 files changed, 162 insertions(+), 4 deletions(-) diff --git a/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md b/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md index 093e1b2..fab425b 100644 --- a/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md +++ b/docs/OBSERVATORY_REALTIME_PROFILES_EXECPLAN.md @@ -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 и готовая автономия не отождествляются. diff --git a/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md b/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md index ed50abd..6d2c504 100644 --- a/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md +++ b/experiments/perception/PERCEPTION_STREAM_STAGE1_2026-09-01.md @@ -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 остаются открытыми.