docs(perception): record decoder parity and remaining full-graph bridge
This commit is contained in:
@@ -1454,3 +1454,112 @@ camera decoder и causal sensor adapter, соединяющие этот ingress
|
||||
parity/timing на новом входе. Network/gRPC/authentication, constant controller
|
||||
root/recovery/inventory, standalone image и product cutover остаются открытыми.
|
||||
Этап 2 не закрыт, этапы 3–4 не начаты; actuation=false.
|
||||
|
||||
## 2026-09-02 13:09 МСК — этап 2, инкремент 4: fMP4 → persistent decoder
|
||||
|
||||
Коммиты: `350366b` (общий parser/decoder и synthetic tests), `f102712`
|
||||
(Worker probes). Это входная часть runtime, **не новый запуск полного графа**.
|
||||
Никакие модели, thresholds, source clock, GPU clocks или ограничения Docker
|
||||
полного профиля не менялись. Четыре Mission Core GPU-сервиса не останавливались.
|
||||
|
||||
### Реализованная граница
|
||||
|
||||
Из `sessions.media` выделен прежний bounded ISO-BMFF timing parser; archive API
|
||||
сохраняет свои исключения. Новый decoder не импортирует session store/materializer,
|
||||
не принимает path, frame count, duration или EOF. Принимает init ≤64 KiB и один
|
||||
полный fMP4 fragment ≤1 MiB. Объявленный subset: H.264, один video track, native
|
||||
800×600, один sample, явные moof-relative offset/size, без composition offset.
|
||||
Первый fragment/frame проверяется как random-access/keyframe; DTS непрерывен.
|
||||
Persistent codec выдаёт ровно один BGR кадр текущего PTS, без flush и будущих
|
||||
пакетов. B-frames, иной layout/raster, multi-sample, пропуск или неоднозначный
|
||||
native output завершают decoder; молчаливого fallback нет.
|
||||
|
||||
Первый рабочий вариант открывал `init + current fragment` через PyAV на каждом
|
||||
кадре. Полнофайлового барьера уже не было, но повторялся stream probing.
|
||||
В принятом варианте bounded parser проверяет размер/offset единственного AVCC
|
||||
sample и передаёт его непосредственно persistent H.264 codec. NumPy импортируется
|
||||
до readiness. Только init открывается через PyAV; decode не читает файлов.
|
||||
|
||||
### Worker CPU-only A/B и отдельный reference
|
||||
|
||||
Эксперименты `perception-stage2-decoder-worker-20260902T1250MSK` и
|
||||
`perception-stage2-decoder-direct-worker-20260902T1305MSK`: последовательно,
|
||||
network none, без GPU request, 2 CPU / 512 MiB; process address-space limit 1 GiB.
|
||||
Исходные 128 fMP4 fragments поступают по одному на исходном 1× времени.
|
||||
Старая готовая MP4 используется **только** отдельным reference-процессом OpenCV
|
||||
для сравнения пикселей, не монтируется в новые decoder-прогоны. Reference не
|
||||
paced, поэтому его throughput не сравнивается с новым source-paced latency.
|
||||
|
||||
| Метрика, ms | Первый per-fragment demux | Direct sample / persistent codec |
|
||||
| --- | ---: | ---: |
|
||||
| p50 | 10.506 | 5.984 |
|
||||
| p95 | 19.927 | 11.156 |
|
||||
| p99 | 20.920 | 18.675 |
|
||||
| max | 68.909 | 38.066 |
|
||||
| Первый кадр | 68.909 | 18.675 |
|
||||
| Codec init, отдельно | 17.854 | 21.103 |
|
||||
| BGR parity с reference | 128/128 exact | 128/128 exact |
|
||||
|
||||
Каждый кадр декодирован до чтения следующего source fragment. Direct peak RSS
|
||||
59,192 KiB. Это один bounded CPU A/B, не статистическая квалификация всего
|
||||
профиля и не обещание аналогичного выигрыша при одновременной CPU-части графа.
|
||||
|
||||
### Бинарный вход с настоящим декодером
|
||||
|
||||
`perception-stage2-decoded-ingress-worker-20260902T1310MSK`: существующий
|
||||
отдельный source process → IPC v2 → FragmentDecoder в CPU-only probe container
|
||||
(2 CPU / 768 MiB). Receiver по-прежнему не получает длину записи. Защита raw
|
||||
headers/reassembly сохранена; init/extradata и decoder scratch резервируются
|
||||
в общем 16-MiB mailbox **до** использования. Native codec/DPB дополнительно
|
||||
ограничены container RSS envelope; это не всеобъемлющий Python byte counter.
|
||||
|
||||
- 103/103 raw events exact: init 1 + camera 32 + LiDAR 34 + pose 36; timestamp,
|
||||
sequence, source identity, payload length/SHA сохранены.
|
||||
- 32/32 decoded BGR exact против независимого reference. Первый decoded callback
|
||||
за 3.071 s до source End marker; 31/32 до marker, последний дренируется перед
|
||||
обработкой End получателем. Это нормальная финальная доставка, не EOF barrier.
|
||||
- Source-due → decoded/hash callback p50/p95/p99/max:
|
||||
9.257 / 19.317 / 26.019 / 26.019 ms. Decode+hash p95/p99 11.635/19.698 ms.
|
||||
Эти интервалы не включают модели, geometry, result scene, сеть или browser.
|
||||
- Wire 4,061,695 bytes; peak accounted input 5,727,751 bytes; остаток 0;
|
||||
cgroup peak 84,332,544 bytes. Source release lag max 5.838 ms.
|
||||
- Negative EOF между фрагментами: started=1, completed=0, incomplete=1;
|
||||
никакого payload callback, terminal=failed, lease/input bytes освобождены.
|
||||
|
||||
PyAV18 wheel отсутствовал в исходном diagnostic image. Загружен публичный
|
||||
`av==18.0.0` (35,536,910 bytes, SHA-256
|
||||
`ae56b40b6f8b067a8ad2dac664fbfbabac7f7a55b9a7bb031eb99289252bc017`), затем
|
||||
установлен offline/no-deps в приватный experiment target. Общая система,
|
||||
Goose Python и image не менялись. Target read-only; его file hashes сохранены
|
||||
в dependency manifest. Это явный временный mount, не standalone packaging.
|
||||
|
||||
246 focused tests PASS; повтор session API + decoder — 55 PASS. Ruff и mypy
|
||||
трёх source modules PASS; full suite и модели на Mac не запускались.
|
||||
Все временные probe/dependency containers и source children завершены.
|
||||
Triton ready=200, Mac 8000=200, 8765 закрыт. Ollama/Frigate exited/restart=no;
|
||||
GPU auto P8, 982 MiB, power limit 450 W, без изменения частот.
|
||||
|
||||
### Evidence и следующий шаг
|
||||
|
||||
Принятый manifest: 43 artifacts, SHA-256
|
||||
`612295eabbc8f203ad9b037a69ac9cf97b2df3134b087d9e51a9786738423f2f`,
|
||||
`.runtime/perception-stage2-decoded-ingress-worker-20260902T1310MSK/manifest.json`.
|
||||
Связанные sealed manifests: demux/reference/dependency —
|
||||
`6a0090f6e1ec11aba436441afacdc0146902a5f911a57a8f989038764dab5d2f`
|
||||
(22 artifacts); direct decoder —
|
||||
`0eb32c2c5823130dec87b4e11d825d984b7ee373453b8b4f8b17a4729d5f8134`
|
||||
(14 artifacts). Снимки code packs, отчёты, per-frame hashes, timestamps,
|
||||
команды и dependency inventory сохранены; реальные inputs в Git не добавлены.
|
||||
|
||||
**Граница:** cloud/pose пока передаются без изменения, но не связываются здесь
|
||||
в causal scene; calibration identity у hash/decode probe синтетическая и не
|
||||
допускает model scene. Нативный decoder ещё требуется изолировать supervised
|
||||
CPU child внутри полного runtime; добавить bounded RPC, causal sensor cut на
|
||||
момент camera release и handoff decoded ownership в общий mailbox. После этого
|
||||
запустить тот же DDRNet/RF-DETR/geometry/motion/TGS/policy граф и проверить
|
||||
raw parity / timing на новом binary input, без `/source.mp4`.
|
||||
|
||||
Последний **полный** p95/p99 остаётся 124.98/136.12 ms, fresh 76/128. Не вычитать
|
||||
decoder-выигрыш из этих значений и не объявлять real-time qualification.
|
||||
Network/controller/recovery/inventory, standalone image и product cutover
|
||||
остаются открытыми. Этап 2 продолжается; этапы 3–4 не начаты; actuation=false.
|
||||
|
||||
Reference in New Issue
Block a user