Перейти до основного вмісту

Архітектура та проєктування репозиторію

Ця сторінка призначена для розробників, яким необхідно зрозуміти, як структурована бібліотека, де розташовані основні компоненти та як розширити структуру, не порушуючи її модульність і контракти середовища виконання.

Фреймворк проти середовища

Слово «Neat» використовується для позначення двох пов’язаних, але різних аспектів:

  • Neat Library: бібліотека C++/Python і середовище виконання, що міститься в цьому репозиторії. Вона завантажує модель. створює пакети, формує конвеєри, перевіряє контракти, працює на апаратному забезпеченні Modalix і надає доступ до публічного API.
  • Neat SDK / середовище: контейнеризований процес розробки, що охоплює роботу з фреймворком. зокрема, DevKit Sync, спільні робочі простори та інструменти для агентів.

Під час внесення змін до цього репозиторію оптимізуйте його для властивостей фреймворку, які підтримують як людей, так і агентів: чіткі API, детермінована поведінка, структуровані засоби діагностики, сувора перевірка та стабільні публічні контракти.

Для чого призначена ця бібліотека?

Основні користувачі

Розробники, які бажають:

  • Створюйте конвеєри з використанням повторно використовуваних складових (без написання стандартного коду GStreamer).
  • Забезпечте перевірку конвеєрів на ранніх етапах (з урахуванням вимог безперервної інтеграції) та швидко аналізуйте причини збоїв.
  • Запускайте конвеєри та обробляйте кадри мовою C++ за допомогою appsink.
  • За бажанням, можна передавати дані конвеєра через RTSP (за допомогою gst-rtsp-server).
  • Надавайте код машинного навчання через вихідні дані, оптимізовані для тензорів, без необхідності писати складний код для GStreamer.

Права власності на пакет

Обраний основний артефакт є джерелом істини для пакетів Neat, LLiMa та Internal Debian, які встановлюються разом. Основний модуль використовує та передає цей артефакт без вибору або переписування версій залежностей. Пакет, що знаходиться поза межами артефакту, залишається у власності платформи; у разі виникнення несумісності платформу слід оновити, а не ремонтувати за допомогою основного модуля або LLiMa.

Типові робочі процеси

  • Декодування/обробка: файл або RTSP -> демультиплексування/розбір -> декодування -> перетворення/налаштування параметрів -> appsink -> споживач, написаний на C++
  • Перевірка: збірка + аналіз + попередня обробка (У СТАНІ ПАУЗИ), щоб на ранніх етапах виявити проблеми, пов’язані з узгодженням.
  • Надання RTSP: передавайте синтезовані кадри в конвеєр RTSP-сервера, використовуючи appsrc.
  • Адаптер тензорів зображень/відео: зображення/відео/RTSP -> декодування -> перетворення/масштабування -> add_output_tensor(...) -> Run::pull_tensors().
  • Навчальні матеріали: почніть з Навчальні матеріали, щоб отримати доступ до структурованого навчального курсу, який можна використовувати на практиці.

Стандартизований виробничий конвеєр (джерело істини).

Канонічний «шлях для виробничого середовища» для цього репозиторію такий: вхідні дані -> попередня обробка -> MLA -> постобробка. Джерело істини знаходиться тут: tests/e2e_pipelines/obj_detection/sync_yolov8_test.cpp.

Коли цей тест змінюється, оновіть файл README та розділ «Архітектура», щоб забезпечити узгодженість документації.

Концептуальна модель (бізнес-логіка ↔ сполучна ланка конвеєра)

Ваша програма зберігає бізнес-логіку, а фреймворк забезпечує зв’язок між елементами конвеєра.

Business logic
|
v
Nodes/Graph fragments -> GStreamer fragments -> caps negotiation -> runtime (Run)
| |
+-----------------------------------------------------------+
Sample / Tensor

Основні поняття

Ця структура навмисно організована навколо невеликої кількості ключових понять. Більшість коду, який пише користувач, стосується лише Model, Graph, Run, Tensor та Sample; розробники, що працюють на нижчому рівні, також працюють з Node, повторно використовуваними фрагментами графа, аналізом MPK-контрактів і внутрішньою структурою графа.

КонцепціяРоль
Архів моделіЗапакований у формат .tar.gz артефакт, що містить контракт для виконання MPK, конфігурації, призначені лише для плагінів, бінарні файли моделі та артефакти ядра.
ModelПублічний завантажувач для архіву моделі у форматі .tar.gz. Він аналізує контракт MPK, виконує планування маршруту, надає доступ до етапів моделі та забезпечує прості точки входу для виконання run(...) / Graph.
TensorВведений числовий блок даних із зазначенням типу даних, розмірності, структури, способу зберігання, пристрою та семантичних метаданих.
SampleОболонка для даних, що використовуються під час виконання, навколо тензорів, списків тензорів або наборів. Перевірте Sample::kind перед читанням полів.
NodeАтомарна стадія конвеєра, яка генерує детермінований фрагмент GStreamer і повертає імена відповідних елементів.
Фрагмент графа, який можна повторно використовувати.Готовий Graph, який розширюється до кількох вузлів, наприклад, декодованого вхідного потоку RTSP або етапів моделі.
GraphМежа збірки та перевірки. Вузли, моделі та фрагменти графа, які можна повторно використовувати, стають узгодженим, структурованим конвеєром.
RunАктивний об’єкт конвеєра, який повертається функцією Graph::build(...); він відповідає за життєвий цикл операцій над даними (завантаження/вивантаження/середовище виконання).
ГрафВикористовуйте граф для побудови DAG (направленого ациклічного графа) всередині одного конвеєра; використовуйте граф середовища виконання для координації етапів/виконань між різними конвеєрами.

Читайте зв’язки зліва направо:

model archive on disk -> Model -> Graph fragments/Nodes -> Graph -> Run
|
v
Tensor/Sample flow

Model є початковою точкою для користувачів-початківців, але це не окремий модуль виконання. Він використовується для створення фрагментів/вузлів графа, які можна додавати до Graph. Graph є центральною концепцією для збирання; Run – це активний об’єкт після створення.

Принципи дизайну для авторів

Це основні принципи архітектури, що забезпечують надійність роботи фреймворку. Використовуйте їх, коли обираєте між різними варіантами реалізації.

  • Детермінованість перемагає. Зберігайте назви елементів, згенеровані рядки для конвеєра, серіалізовані дані конвеєра. поля звіту та результати тестування мають бути відтворюваними. Діагностика та цикли роботи агента залежать від стабільних ідентифікаторів.
  • Зручність налагодження є пріоритетною. У разі виникнення помилок мають генеруватися структуровані дані, а не лише текстові рядки: GraphReport.error_code, repro_note, повідомлення шини та конвеєри бекенду, які можна повторно запускати.
  • Не використовуйте непомітний механізм резервного копіювання. Не приховуйте помилки вхідних даних моделі або збої апаратного забезпечення/середовища виконання, просто мовчки ігноруючи їх. перетворення форматів, зміна сімейств графів, перехід на використання центрального процесора або обробка помилок плагінів.
  • Здійснюйте перевірку перед запуском. Віддавайте перевагу структурній перевірці, перевірці великих літер, форми та відповідності вимогам перед початком роботи в середовищі виконання. починаються потоки або виділяються апаратні ресурси.
  • Контракт MPK є еталонним джерелом істини. Основні функції: маршрутизація, тип даних, форма, квантування та рішення щодо кожного етапу мають надходити з файлів mpk.json / *_mpk.json. Файли JSON для кожного етапу є приватною власністю плагіна.
  • Логічний ранг і геометрія, що використовується під час виконання, є окремими поняттями. Основний модуль зберігає дані, створені MPK. frame_shape використовується як логічний контракт вихідних даних і, за потреби, генерує чітку геометрію MLA. Об’єкт 2-го рангу приймається як NC або HW лише тоді, коли оголошені діапазони байтів ідентифікують єдину інтерпретацію; неоднозначні або суперечливі контракти призводять до помилок під час завантаження моделі.
  • Публічні API залишаються стабільними. Публічні заголовні файли, що містяться в include/*, встановлюються та підтримуються. Віддавайте перевагу поступовим змінам і механізмам відмови від застарілих функцій, а не різким змінам у структурі.
  • Паралельність має бути обмеженою та відстежуваною. Робота в потоці даних має бути легкою; діагностика на стороні зонда потребує використання атомарних операцій або еквівалентних механізмів безпечної обробки в багатопотоковому середовищі; завершення процесу не повинно призводити до зависання.

Шлях виконання моделі.

Для конвеєрів, що базуються на моделях, загальна схема така:

input Sample/Tensor
-> optional preprocessing / format normalization
-> MLA inference stages selected from MPK contract
-> optional postprocessing / box decode
-> output Sample/Tensor

Видима для користувача угода Model навмисно простіша, ніж апаратна угода MLA. MLA може вимагати використання INT8/BF16 і тесельованих макетів, тоді як код користувача зазвичай працює з FP32 і звичайними макетами тензорів. Фреймворк усуває цю різницю за допомогою адаптерних етапів, керованих маніфестом.

Попередня та остаточна обробка є чіткими етапами/параметрами фреймворку. Несумісність форматів, відсутність необхідних метаданих для попередньої обробки, недоступний диспетчер MLA, недійсний архів моделі або угода MPK, або невдала угода щодо обмежень повинні відображатися як структурована помилка, з якою можна працювати, а не як прихована корекція в середовищі виконання.

Структура репозиторію.

Структура високого рівня.

  • include/ – загальнодоступні заголовкові файли (підтримуваний інтерфейс API).
  • src/ – реалізації.
  • docs/ – документація (цей файл)
  • examples/ – невеликі приклади, які можна запустити.
  • tests/ – модульні/інтеграційні тести.
  • python/ – вихідні коди пакета pyneat, прив’язки nanobind і тести для Python.
  • old_* — знімки застарілої монолітної реалізації, що зберігаються для довідки/переходу на нову систему.

Відкрите дерево заголовкових файлів (include/).

Загальнодоступні заголовкові файли розміщуються в include/<module>/.... Приклади: include/pipeline/Graph.h, include/model/Model.h.

Загальнодоступні заголовкові файли, що містять корисні функції:

  • include/neat.h (парасолька)
  • include/neat/runtime.h
  • include/neat/models.h
  • include/neat/nodes.h
  • include/neat/node_groups.h

Навмисно не передбачено загальнодоступного include/neat/graph.h заголовного файлу. Тести середовища виконання/компілятора, які потребують базової структури графа нижчого рівня, повинні безпосередньо використовувати вузький набір include/graph/... заголовних файлів. Програми, приклади та загальнодоступна документація повинні використовувати єдиний загальнодоступний simaai::neat::Graph з <neat.h>.

Внутрішні заголовки та шляхи до плагінів середовища виконання.

Публічні заголовкові файли, що розміщені в include/, встановлюються та розглядаються як стабільний API. Внутрішні заголовкові файли, що розміщені в src/**/internal, не встановлюються; у прикладах/навчальних матеріалах слід використовувати лише публічний API.

Примітки щодо середовища виконання:

  • Якщо ви використовуєте вбудовані плагіни GStreamer у deps/gst-plugins, встановіть. GST_PLUGIN_PATH та/або GST_PLUGIN_PATH_1_0, щоб додати цю директорію.
  • Якщо встановлено за допомогою cmake --install, плагіни розміщуються в каталозі: ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/sima-neat/gst-plugins. Додайте цей шлях до GST_PLUGIN_PATH та/або GST_PLUGIN_PATH_1_0.
  • Використовуйте scripts/use_neatdecoder.sh, щоб задати шляхи до плагінів для поточної оболонки.
  • Якщо встановлюєте плагіни для всієї системи, перезберіть кеш GStreamer.

Запланований vs. стабільний (інтерфейс API)

Площа / APIСтатусПримітки
Основний API конвеєра (Graph, Run, Tensor, Sample)СтабільнийОсновна підтримувана поверхня C++.
Внутрішні компоненти конструктора (Node, приватні допоміжні функції для роботи з векторними вузлами, GraphPrinter).ВнутрішнійПідтримка лише формату STL, попереднє компонування перед використанням GStreamer.
API моделі (Model, фрагменти графа, які можна повторно використовувати)СтабільнийСтандартний шлях інтеграції з архівом моделей.
include/policy/*СтабільнийМінімальні перевірені контракти та налаштування політики за замовчуванням (Decoder, Encoder, Memory, RTSP).
include/nodes/groups/ImageToH264RtspGroup.hЗапланованоПорожня група-заповнювач.
Зв’язки для Python (python/, pyneat)БетаЗв’язування та пакування на основі Nanobind розміщуються безпосередньо в репозиторії; API зосереджується на Tensor, Graph/Run, Model та основних допоміжних функціях для вузлів/груп.

Модулі та сфери відповідальності

builder/ — підтримка контрактів для вузлів і приватної лінійної композиції (без використання GStreamer).

Мета: Визначити, як конвеєри складаються з логічних частин.

Основні типи:

  • Node – інтерфейс, реалізований кожною складовою конвеєра.
  • приватні допоміжні функції для роботи з векторами вузлів і GraphPrinter — утиліти для створення композицій і засоби діагностики.

Правило: засіб створення має переважно використовувати лише STL. Він не повинен містити об’єкти середовища виконання GStreamer.

nodes/ – типові складові конвеєра.

Мета: Надати готові до використання реалізації Node, які генерують детерміновані фрагменти GStreamer.

Приклади:

  • nodes/io/HttpSource, nodes/io/RTSPInput, nodes/io/StillImageInput
  • nodes/common/* (вхідні, черга, вихід тощо).
  • nodes/sima/* (вузли для розкодування/кодування/аналізу/обробки платежів від SiMa.ai)
  • nodes/rtp/* (вспомігальні функції для дешифрування/обробки корисного навантаження)
  • nodes/groups/* (поширені рецепти для багатокомпонентних систем)

Контракт: Кожен вузол повинен забезпечувати:

  • backend_fragment(index) — фрагмент GStreamer для цього вузла за вказаним індексом.
  • element_names(index) – детерміновані імена елементів, що належать цьому вузлу (для діагностики та забезпечення відповідності).

gst/ — набір невеликих утиліт GStreamer.

Призначення: Невеликі обгортки/допоміжні функції для типових шаблонів GStreamer.

Приклади:

  • ініціалізація (GstInit)
  • аналіз рядків для запуску (GstParseLaunch)
  • розпакування/перетворення даних у рядок для шини (GstBusWatch)
  • допоміжні функції для обробки великих літер / інтроспекція елементів (GstHelpers, GstIntrospection)
  • тачпади / допоміжні інструменти для зондування (GstPadTap)

Правило: gst/ не повинен залежати від pipeline/ (щоб уникнути циклічних залежностей і надмірного розростання «службового шару»).

pipeline/ – оркестрація середовища виконання та публічний API.

Мета: Керування повним життєвим циклом середовища виконання: створення -> аналіз -> запуск -> використання -> завершення, з можливістю діагностики.

Основні типи:

  • Graph — основна точка входу для користувачів.
  • Run – обробник запущеного конвеєра з використанням API для надсилання та отримання даних.
  • Sample — структурований блок даних, що повертається у відповідь на запити.
  • GraphReport – структурована діагностика збоїв, зупинок і відтворення.
  • Errors — винятки (NeatError), що містять звіт.

Семантика обробки помилок.

GraphReport.error_code — це стандартне поле для автоматизованої класифікації помилок. Структура середовища виконання/збірки/вхідних/вихідних шляхів відображає критичні помилки на стабільні групи коду:

  • misconfig.pipeline_shape
  • misconfig.caps
  • misconfig.input_shape
  • misconfig.input_capacity
  • misconfig.media_caps
  • misconfig.tensor_dtype_missing
  • misconfig.option_out_of_range
  • build.parse_launch
  • build.pipeline_syntax
  • build.plugin_missing
  • build.property_invalid
  • runtime.pull
  • runtime.element_failed
  • runtime.output_timeout
  • io.parse
  • io.open
  • io.file_not_found
  • io.permission_denied
  • io.rtsp_connection_failed
  • io.camera_not_found
  • codec.*, resource.*, infra.* та internal.*.

Помилки GStreamer проходять через один внутрішній парсер, класифікатор і модуль рендерингу. Класифікація віддає перевагу версіонованому ідентифікатору діагностики Neat, потім нативній області/коду GStreamer і фабриці елементів, а потім використовує більш вузькі відображення сумісності для старих плагінів. У разі невідомих помилок використовується runtime.element_failed; вони не повідомляються як misconfig.media_caps, якщо переговори фактично не завершилися невдало. Коли конвеєр генерує кілька помилок, відображається найбільш конкретна основна причина, і кожна помилка зберігається в журналі.

GraphReport.repro_note – це зведена інформація, призначена для користувача. Продуктивний рендеринг містить причину, виражену простою мовою, відповідні спостережувані/очікувані значення, конкретні дії користувача та стабільний ідентифікатор діагностики. Необроблені рядки плагінів, розташування джерел і область/код GStreamer призначені лише для налагодження. Закладений загальнодоступний код додається один раз під час створення NeatError. GraphReport.bus є джерелом істини для деталей помилок плагінів/середовища виконання. Для процесів build(input), GraphReport.build_adaptation фіксує вирішену політику/можливість форми, джерела для початкових/максимальних обмежень, джерело захисту байтів і застосовані/пропущені дії адаптації. Для процесів отримання даних у середовищі виконання, які не викликають виключень, PullError.code використовує ту саму таксономію. Помилки робочого процесу вхідного потоку зберігають типізований код помилки та передають його через межу робочого потоку, тому Run::pull() і перекладач винятків Python відображають одну й ту саму NeatError.

Порядок пріоритетів підтримки:

  1. відро за error_code
  2. прочитайте repro_note
  3. спочатку перевірте наявність помилок у першому терміналі bus.
  4. відтворити з використанням repro_gst_launch

Внутрішня діагностика конвеєра.

У рамках src/pipeline/internal/ (лише для внутрішнього використання):

  • Diagnostics.h – спільні типи діагностичних даних, що використовуються в середовищі виконання:
    • DiagCtx (журнал шини + звіти вузлів + лічильники меж/елементів)
    • BoundaryFlowCounters (атомарні лічильники, значення яких оновлюються з потоків даних).
    • ElementTimingCounters (атомарний облік часу обчислень для кожного елемента)
    • ElementFlowCounters (атомарна статистика потоку для кожного елемента)
  • GstDiagnosticsUtil.h — допоміжні функції для форматування та збору даних діагностики GStreamer.

Контракт щодо статичного контексту маніфесту SIMA.

Для конвеєрів моделей статичні дані про контракт для етапів/тензорів створюються у фреймворку та передаються як GstContext на рівні конвеєра:

  • Тип контексту: sima.model.manifest.v1
  • Поля контексту:
    • manifest_version
    • manifest_json (пакет даних для забезпечення сумісності зі старими версіями)
    • manifest_accessor_v1 (вказівник на таблицю доступу, сумісну з ABI)
    • необов’язковий session_id, model_id
  • Визначення прав власності/терміну дії пов’язане з терміном дії конвеєра; плагіни використовують покажчики та копіюють дані. їм це потрібно.
  • Межа репозиторію: цей репозиторій не повинен додавати залежності, які виникають під час збірки, від репозиторіїв плагінів/диспетчерів. Інтеграція здійснюється лише через інтерфейс (середовище виконання GstContext, властивості, обмеження/метадані та контракти C-ABI).

Пріоритетність вирішення для перенесених полів є детермінованою:

  1. визначати на основі сигналу контракту/середовища виконання (форма/метадані/можливості)
  2. шлях до властивості в контексті/за замовчуванням
  3. критична помилка шини (ніколи не призводить до аварійного завершення/SIGSEGV)

StageTransformRuleRegistry (внутрішній) — це єдина таблиця відповідностей, яка визначає, які не-MLA етапи успадковують контракти тензорів від вхідних даних MLA порівняно з вихідними даними MLA, і коли відбувається поширення квантування вихідних даних. Це забезпечує чітке та перевіряєме визначення попередніх/подальших етапів обробки.

Для мігрованих плагінів SIMA, що використовують шаблон-агрегатор, конфігурація середовища виконання тепер базується на розв’язанні, що керується контекстом/властивостями:

  1. статичні поля на етапі збірки отримуються з контексту маніфесту.
  2. налаштування для середовища виконання беруться зі значень за замовчуванням, визначених у властивостях/контексті.
  3. якщо обов’язкові поля не заповнено, виникає явна помилка (у фреймворку не передбачено резервного варіанту у форматі JSON).

Для simaaiprocesscvu, схема з’єднань, отриманої з CM, спочатку визначає структуру, а sink_pad_tensor_index_map використовується для детермінованого відображення з багатьох входів; застарілі імена буферів вхідних даних використовуються лише як резервні.

Якщо вказано, logical_stage_id визначається на основі властивостей конвеєра stage-id/stage_id; в іншому випадку використовується назва елемента. Конструктори фрагментів шляху моделі SIMA встановлюють stage-id для елементів simaaiprocesscvu, simaaiprocessmla та simaaiboxdecode за замовчуванням.

Клас YOLO26 BoxDecode, кількість контрактів.

Для моделей YOLO26, які використовують керування на основі моделі для виявлення об’єктів, визначення поз і сегментації, глибина класу MPK є авторитетним показником кількості класів. Model::Options::num_classes = 0 обирає це обчислене значення. Додатне значення має відповідати йому; у разі розбіжності виникає помилка під час створення контракту, і відображається налаштоване значення, значення, отримане з MPK, і тип декодування. Це запобігає використанню недійсної кількості класів для інтерпретації згрупованого макета необроблених даних. Моделі SSD і попередні версії YOLO26, які не використовують визначення поз, зберігають свою існуючу поведінку з явним перевизначенням, тоді як декодери для визначення поз і SuperPoint зберігають свої правила, специфічні для кожної родини моделей.

Контракт SuperPoint BoxDecode.

SuperPoint використовує ту саму межу між MPK і статичним маніфестом, що й інші родини BoxDecode, якими керує модель, з наступними додатковими інваріантами:

  • Запис MPK містить ідентифікатори тензорів детектор-логітів і дескриптор-сітки, а також інформацію про зберігання. представлення, факти щодо типу даних/розміру, інформація про чисельний профіль, а також необов’язкові явні параметри NMS та параметри контролю меж. Основний модуль ніколи не визначає ці ролі на основі значень тензора.
  • Основний модуль пов’язує рівно один тензор з кожною роллю, перевіряє відбиток профілю та підтримувані представлення, застосовує явні Model::Options::superpoint перевантаження та обробляє лише пропущені значення за замовчуванням профілю. Зміна профілю повторно обчислює похідні значення за замовчуванням, зберігаючи при цьому параметри, які були явно визначені в MPK або API.
  • Версія статичного маніфесту ABI передає розв’язаний контракт до simaaiboxdecode. Плагіни. під час налаштування слід використовувати лише тимчасові вказівники на маніфест, і необхідно скопіювати будь-які необхідні дані для подальшого використання в середовищі виконання; Основний модуль зберігає право власності на маніфест протягом усього часу роботи конвеєра.
  • Вихідні дані виробництва використовують дротяний формат FEATURE_POINTS_V1 і містять семантичні метадані. FEATURE_POINTS_LEGACY_A65_V0 доступний лише за умови явного вибору для забезпечення сумісності; користувачі не повинні визначати формат на основі розміру буфера.

contracts/ – правила перевірки.

Мета: Забезпечити кодування інформації про те, як має виглядати «правильно налаштований конвеєр», а не лише підтвердження успішного виконання функції «gst_parse_launch».

Приклади:

  • інтерфейси та реєстри валідаторів
  • структурований ValidationReport

Цей шар можна використовувати для безперервної інтеграції та для виявлення проблем до початку роботи програми в середовищі виконання.

policy/ – поведінка, яку може налаштовувати користувач.

Мета: Централізація параметрів налаштування (значення за замовчуванням, обмеження пам’яті, вибір політики для кодувальника/декодувальника/RTSP).

Мета полягає в тому, щоб зробити параметри налаштування явними та легкодоступними, а не прихованими в розрізненому коді.


Інтеграція з архівом моделей.

Призначення: Завантаження архівів моделей .tar.gz за допомогою Model та адаптація отриманого контракту для виконання MPK до фрагментів графа, які можна використовувати для маршрутизації.

Безпечний завантажувач архівів є внутрішньою деталлю реалізації; код програми повинен створювати Model і формувати model.graph() або фрагменти, специфічні для певного етапу.

Типове використання:

simaai::neat::Model model("resnet_50.tar.gz");
simaai::neat::Graph graph;
graph.add(model.graph());

Фрагменти моделі на етапі розробки.

Мета: Створити попередню обробку, процес виведення, подальшу обробку або повний маршрут, що надається Model, не розкриваючи внутрішній завантажувач архіву.

Основні API:

  • Model::preprocess()
  • Model::inference()
  • Model::postprocess()
  • Model::graph()

Це використовується для гібридних процесів, де попередня обробка виконується один раз, а MLA/BoxDecode запускаються в окремому графі або потоці.

Де виконується обчислення (центральний процесор / графічний процесор / прискорювач машинного навчання)

Маршрутизація процесора визначається контрактом MPK (етапи CVU/MLA, визначені в архіві моделі), а також додатковими налаштуваннями, що застосовуються під час роботи в середовищі виконання:

  • Model::Options визначає параметри попередньої та подальшої обробки, іменування та буферизації.
  • SIMA_MLA_NEXT_CPU може замінювати наступний етап для MLA в деяких конфігураціях.
  • Власне, вузли конвеєра мають декларативний характер; фактичне виконання відбувається у плагінах GStreamer та їхніх конфігураціях.

Практичне значення: збільшення кількості буферів і чітке визначення маршрутів може покращити пропускну здатність, тоді як невідповідність типів даних або недостатній розмір буферів призведе до швидкої відмови під час узгодження.

Модель середовища виконання (як відбувається виконання).

Ініціалізація

Усі точки входу в середовище виконання викликають єдину безпечну процедуру ініціалізації:

  • gst_init_once() (безпечний для використання в багатопотоковому середовищі, std::call_once)

Крім того, під час роботи програми можна перевірити, чи встановлено необхідні плагіни:

  • require_element("appsink", ...) тощо.

Створення конвеєрів

Graph створюється шляхом додавання об’єктів Node та повторно використовуваних фрагментів графа. Використовуйте фрагмент, що враховує кодек, для RTSP, щоб джерело було демультиплексоване та проаналізоване перед декодуванням:

simaai::neat::nodes::groups::RtspDecodedInputOptions source;
source.url = "rtsp://example/live";
source.codec = simaai::neat::nodes::groups::RtspCodec::H265;
source.source_fps = 30;

simaai::neat::Graph graph;
graph.add(simaai::neat::nodes::groups::RtspDecodedInput(source));
graph.add(simaai::neat::nodes::Output());

Зсередини:

  1. Граф забезпечує наявність лише одного об’єкта Node для кожної логічної вершини композиції. Повторні виклики connect(). можна повторно використати цей проіндексований піксель для розгалуження.

  2. Зміна композиції фіксується як єдине ціле або повністю скасовується.

  3. Граф запитує у кожного вузла backend_fragment(i) і об’єднує фрагменти за допомогою !.

  4. За бажанням, він вставляє розмежувальні маркери між вузлами:

    • identity name=sima_b<i> silent=true
  5. Він аналізує точні прив’язки name=, один раз обробляє їх за допомогою GStreamer і робить перелік створених. об’єктне дерево. Наявність дублікатів або відсутність назв призводить до помилок на етапі подальшої конфігурації.

  6. Він створює DiagCtx:

    • node_reports для забезпечення можливості відтворення результатів.
    • boundaries як BoundaryFlowCounters (атомарні змінні).

Модель взаємодії за принципом «перетягування» в середовищі виконання.

Run володіє чергами введення/виведення та потоком введення:

  • push(...) додає вхідні дані до черги (блокує або відкидає їх залежно від RunOptions::overflow_policy).
  • pull(...) вилучає Sample з черги вихідних даних від appsink.
  • try_push(...) не блокує виконання (повертає значення «false», якщо черга заповнена).

Це підтримує повністю асинхронні конвеєри (розділення на виробника/споживача), а також одноразові обчислення (Graph::run(...)).

Цикл життєдіяльності декодера під час прийому

Перш ніж обрати одноканальний або з’єднаний у граф варіант середовища виконання, Core сканує скомпільований план виконання на наявність вузлів H.264/H.265, що підтримують певний тип, для SimaDecode. Усі відповідні декодери приймаються як одна група, і отримане резервування належить основному Run, поки не зупиняться всі обчислювальні процеси в конвеєрі. Це стосується як лінійних Graph::add(...) конвеєрів, звичайних з’єднаних сегментів, так і об’єднаних гілок реального часу.

Для прийняття необхідна відома ширина, висота та частота кадрів декодера. Core ніколи не визначає частоту кадрів самостійно. Неповний контракт або недоступна додаткова точка входу для прийняття призводить до попередження, і план залишається без змін; у випадку з SIMA_DECODER_ADMISSION_REQUIRE=1, будь-яка з цих умов призводить до помилки до того, як почне працювати апаратне забезпечення декодера. Відхилення через недостатню потужність і неправильні відповіді щодо резервування завжди призводять до помилки.

Зменшення кількості вхідних сигналів у реальному часі.

Програми описують граничні елементи в режимі реального часу за допомогою звичайного Graph::connect(...) і реалізують їх за допомогою звичайного Graph::build(...). GraphLinkOptions містить найновішу політику обробки потоків, ідентифікатор потоку, зарезервоване поле глибини черги та необов’язкові обмеження на обробку необроблених кадрів. Обробка найновіших кадрів у кожному потоці завжди зберігає один очікуючий зразок для кожного потоку.

Компілятор графа виконання, а не програма, визначає, чи можна об’єднати динамічне багатоджерельне з’єднання в один конвеєр GStreamer. Відповідні приватні гілки джерел без вхідних даних обробляються разом із їхнім мультиплексором і споживачем для кожного потоку, щоб декодовані буфери пристрою не перетинали межу appsink/appsrc. Невідповідна топологія обробки найновіших кадрів у кожному потоці залишається сегментованою. Вкладені вже об’єднані сегменти джерел залишаються невідповідними, доки їхні гілки не можна буде рекурсивно зберегти.

Внутрішні часові обмеження меж

Один логічний Graph може бути розбитий на декілька сегментів конвеєра GStreamer. Основний модуль вставляє appsrc на кожній внутрішній межі між ними.

Вставлена межа передає часову шкалу, яку їй було надано, і ніколи не створює власний мітковий час. Лише загальнодоступний, застосунок-власник Input, створює мітковий час.

appsrc генерує мітки часу на основі часу роботи власного сегмента, тому межа, яка генерує мітковий час, надає кожній гілці розгалуження різний час. Відео RTP потім перестає узгоджуватися з метаданими, що описують один і той самий кадр, і жоден застосунок не може це виправити: розбиття використовує додані Input вузли, тому InputOptions, встановлені застосунком, ніколи не досягають вставленої межі.

Під час додавання шляху матеріалізації сегмента:

  • Створіть параметри, що передаються, за допомогою injected_boundary_input_options(...), які є єдиним місцем, де зберігається цей інваріант.
  • Збережіть is_live = true. Очищення цієї опції призведе до зупинки поточних сегментів.
  • Залиште налаштування за замовчуванням для загального доступу InputOptions::do_timestamp без змін, щоб забезпечити коректну роботу. cv::Mat, який не містить інформації про час, все одно отримує її під час передавання.

Межі забезпечують передавання збереженого GstBuffer без копіювання, тому мітка часу, яка вже існує, зберігається під час передавання. Відмова від створення нової мітки часу ніколи не призведе до її видалення.

Спеціалізація вхідних контрактів

Деякі складні вузли конвеєра мають більше ніж одне безпечне представлення бекенду. Компілятор графа спеціалізує ці вузли на основі статично визначеної OutputSpec; він не змінює загальний граф і не визначає постійну топологію на основі першого зразка під час виконання. Контракт Derived або Authoritative може вибрати оптимізоване представлення. Hint, невідомий формат/пам’ять або відсутність можливостей бекенду вибирають консервативне представлення.

Наприклад, необроблений VideoSender пропускає перетворення NV12 лише для стабільного контракту NV12 у системній пам’яті або пам’яті SiMaAI, коли neatencoder оголошує про свою можливість input-layout-aware=true (врахування макета вхідних даних). OutputSpec наразі не містить інформацію про розміри та зміщення площин, тому жоден домен пам’яті не обходить цю перевірку можливостей. Відсутність або хибність можливості розглядається як відсутність підтримки, тому Core залишається безпечним зі старими пакетами Internals.

Геометрія необробленого відео та фізичний макет зберігання залишаються окремими контрактами. OutputSpec і caps описують видиму ширину та висоту; Core не повинен округляти ці значення до розміру блоку кодека, кроку DMA або вирівнювання висоти поверхні. Плагін, що враховує макет, отримує фізичні зміщення та розміри площин з GstVideoMeta або GstVideoInfo, перепаковує, коли фізичний контракт несумісний, і передає допуск кодека/апаратного забезпечення службі кодування. Це зберігає точну декодовану геометрію, зберігаючи при цьому вирівнювання, специфічне для пристрою, поза загальним API графа.

Аналіз і запуск.

У бібліотеці в основному використовуються:

  • gst_parse_launch(pipeline_string, &err)

Це забезпечує гнучкість і можливість налагодження (ви можете повторити точну послідовність символів за допомогою gst-launch-1.0).

Біг

Типовий процес (Graph::build() / Run):

  1. Забезпечуйте виконання умов контрактів (наприклад, «останній крок» для build() + виконання).
  2. Створіть рядок конвеєра (плюс, за бажанням, додайте межі).
  3. Конвеєр обробки даних
  4. За бажанням, можна застосувати правила для іменування елементів.
  5. Прикріпіть додаткові датчики для визначення меж.
  6. Встановіть для конвеєра значення PLAYING.
  7. Поверніть Run дескриптор для керування операціями надсилання/отримання.

Термін служби рами (простими словами)

  1. Створення: Вузли перетворюються на детермінований рядок для gst-launch.
  2. Узгодження: GStreamer узгоджує параметри між елементами (формат, розмір, пам’ять).
  3. Запуск: Вхідні дані передаються (або отримуються з джерел) у конвеєр.
  4. Приклад: Appsink повертає Sample / Tensor у ваш код.
  5. Помилка: будь-який збій під час узгодження або в середовищі виконання призводить до виникнення помилки NeatError з відповідним GraphReport.

Узгодження можливостей шифрування відбувається автоматично; у разі виникнення помилок вони виявляються на ранніх етапах (перевірка/попередній перегляд) або під час роботи системи, і ви можете відтворити їх за допомогою діагностичних інструментів (describe_backend() + звіт).

Розподіл прав власності на камери.

CameraInput розміщує neatcamerabridge одразу після параметрів камери та перед будь-якою активною чергою. Під час узгодження міст відповідає на запит GST_QUERY_ALLOCATION, що надходить від попереднього модуля, стандартним пулом і запитує GstVideoMeta. Пул виділяє перевірені площини з одного згорнутого розподілу SiMaAI та експортує один DMA-BUF на кожну площину. Сумісний libcamerasrc імпортує ці DMA-BUF у чергу захоплення ISP. Потім міст розпаковує той самий згорнутий розподіл для подальшої обробки. У суворому режимі будь-який буфер, який не відповідає цим вимогам, відхиляється; копіювання ЦП залишається явним механізмом забезпечення сумісності.

Кількість буферів захоплення, що використовується застосунком, не залежить ні від прихованого ядра CSI-to-ISP RAW, ні від пізнішої черги GStreamer. Необов’язковий аргумент capture_buffer_count для CameraInputWithCaptureBuffers контролює буфери, що зберігаються між виходом ISP, libcamera та застосунком. queue_depth і leaky_queue окремо контролюють затримку та політику відкидання кадрів. Необов’язковий пул сумісності збільшується за потреби і не обмежується цією глибиною черги, тому черга з можливістю втрати кадрів може застосовувати свою політику відкидання, не змушуючи попередній міст спочатку зупинятися.

Розбирання.

Процес завершення роботи розроблено таким чином, щоб забезпечити максимальну надійність. Деякі набори плагінів можуть зависати під час зміни стану; середовище виконання намагається уникнути блокування процесу хоста/CI.

Найпоширеніша схема така:

  • надіслати EOS
  • встановити GST_STATE_NULL
  • непосилання на об’єкти
  • застосуйте механізм захисту за допомогою встановлення тайм-ауту (у разі потреби, замість зависання, використовуйте механізм виявлення витоку даних).

Паралельна обробка в SimaAI

Плагіни SimaAI підтримують кілька конвеєрів в одному процесі. Якщо ви запускаєте кілька конвеєрів одночасно, зробіть назви елементів унікальними за допомогою суфіксів/префіксів назв у GraphOptions або Model, щоб уникнути конфліктів назв у GStreamer.


Обмеження та безпека

  • Формати вхідних даних повинні відповідати встановленим вимогам: InputOptions. Формат/ширина/висота повинні бути узгоджені як у вхідних даних, так і в конфігураціях моделі. У разі виявлення невідповідностей процес переговорів завершується негайно або при спробі передачі вхідних даних.
  • Динамічний вхід із обмеженнями за можливостями: повторне узгодження параметрів дозволяється лише тоді, коли створений граф рекламує динамічні можливості. Графи FullyDynamic можуть повторно узгоджувати параметри геометрії/формату/кількості кадрів/медійні можливості необробленого відео; IngressDynamicCvuOnly дозволяє змінювати геометрію та змінювати формат лише тоді, коли перевірки контракту на етапі створення підтверджують стабільну поведінку вихідного потоку.
  • Динаміка в межах ефективних обмежень: max_* — це жорсткі верхні межі; якщо max_* не задано, width/height/depth діють як неявні верхні межі.
  • Налаштування за замовчуванням для моделі та графа: тепер обидва потоки визначають політику обмеження кількості/максимального значення/кількості байтів за допомогою src/pipeline/internal/InputPolicy.*; Model як і раніше застосовує задокументовані налаштування за замовчуванням, що базуються на метаданих (наприклад, максимальна роздільна здатність 1920x1080), тоді як Graph залишається таким, що керується параметрами вузлів, якщо не налаштовано іншим чином.
  • caps_override визначає пріоритет: якщо встановлено, повторне узгодження блокується, а зміни форми вимагають перебудови.
ПотікЗначення за замовчуванням для початкового значення генератора випадкових чисел.Максимальні значення за замовчуваннямЗа замовчуванням у Byte-guard
Modelпопередня обробка метаданих (за наявності), інакше – визначення на основі формату/налаштувань, заданих користувачем.явно вказано input_max_*; в іншому випадку використовуються значення за замовчуванням (наприклад, 1920x1080, глибина, що визначається форматом).явно вказано RunOptions.max_input_bytes, інакше використовується обмежена оцінка або гнучке значення за замовчуванням із InputPolicy.
Graphпараметри вхідного вузла та/або зразок вхідних даних для ініціалізаціїявно вказано max_*; в іншому випадку, значення визначається неявно на основі початкових даних width/height/depth, якщо їх надано.явно вказано RunOptions.max_input_bytes, інакше використовується обмежена оцінка або гнучке значення за замовчуванням із InputPolicy.
  • Паралельна обробка в SimaAI: можна одночасно запускати декілька конвеєрів; слід забезпечувати унікальність назв елементів.

Поширення атрибутів для кожного кадру.

Джерела додають Sample::attributes як вкладену структуру в GstSimaMeta. Елементи, які зберігають буфер, природним чином містять метадані; основні межі, які виділяють або повторно використовують буфер, глибоко копіюють атрибути та очищають застарілі значення. neatdecoder робить знімок одного й того ж контексту кадру перед декодуванням і відновлює його за допомогою ідентифікатора кореляції, наданого демоном, тому перевпорядковані або відкинуті кадри не можуть переміщувати атрибути на інший вихід. Узгоджений протокол декодера/демона визначає цей контракт кореляції; застарілий протокол декодера залишається лише FIFO.

Підтримувані шляхи та обмеження, видимі для користувача, описані в Атрибути для кожного кадру..

Модель багатопоточності та власності

Потоки

  • GStreamer: потоки для потокового відтворення: перевірка даних, декодування, планування.
  • Потік користувача: appsink. Опитування + періодичне очищення шини.
  • Потік сервера RTSP: основний цикл GLib для режиму gst-rtsp-server.

Правила визначення власника (об’єкти GStreamer)

  • Об’єкти GStreamer використовують механізм підрахунку посилань.
  • Якщо ви зберігаєте GstObject* поза межами області, де його було отримано, ви повинні звільнити його, викликавши gst_object_ref().
  • Завжди викликайте gst_object_unref() рівно один раз після завершення роботи.

Діагностика безпеки багатопотоковості (важливо)

Тести зондів виконуються в потоках даних, тому оновлення діагностичної інформації, отриманої від зондів, має відбуватися без блокувань.

Структура така:

  • BoundaryFlowCounters зберігає атомарні значення.
  • зонди для вимірювання зазору виконують лише атомарні операції fetch_add() / store().
  • у звіті використовується BoundaryFlowCounters::snapshot() для перетворення атомарних значень у BoundaryFlowStats (прості цілі числа).

Це дозволяє уникнути конфліктів доступу до даних, водночас зберігаючи низьку вартість зондування.

Діагностика та моніторинг

DiagCtx фіксує:

  • рядок конвеєра (для відтворення)
  • звіти вузлів (інформація про те, що згенерував кожен вузол)
  • повідомлення, що передаються через шину (за допомогою м’ютексу)
  • лічильники потокових змін на межі (атомарні операції)
  • час обробки елементів + лічильники потоків (атомарні операції)

Датчики для вимірювання потоку на межі

Коли цю функцію ввімкнено, середовище виконання додає зонди для відстеження до граничних елементів identity. Вони відстежують:

  • кількість буферів (на вході/на виході)
  • останній раз зафіксовано в PTS (нс)
  • останній зафіксований час (монотонний, в мікросекундах)

Це використовується для створення зведених даних про «ймовірні місця затримок»:

  • «ми востаннє спостерігали активність на межі X у момент часу T, коли об’єкт входив/виходив за її межі».

Датчики для вимірювання часу спрацювання елементів

Коли цю функцію ввімкнено (SIMA_GST_ELEMENT_TIMINGS=1), середовище виконання додає зонди до вхідних і вихідних портів усіх портів (статичних, динамічних і запитуваних) для кожного елемента та записує src_ts - sink_ts для кожного буфера. Це дозволяє обчислювати час виконання для кожного елемента, не покладаючись на інструментарій плагінів.

Для елементів, які замінюють буфери, реалізація використовує кореляцію GstSimaMeta (ідентифікатор кадру/ідентифікатор потоку) і записує лічильники missed_in/ missed_out.

Датчики для вимірювання потоку елементів

У разі активації (SIMA_GST_FLOW_DEBUG=1), середовище виконання додає датчики для кожного елемента, щоб відстежувати кількість буферів/байтів і зміни параметрів, надаючи інформацію про пропускну здатність для кожного плагіна в графі.

Журналування даних шини та повідомлення про помилки.

Під час роботи система збирає повідомлення з шини в DiagCtx. У разі виникнення помилки (GST_MESSAGE_ERROR), система генерує виняток NeatError, який містить GraphReport та підказки щодо відтворення помилки.

Звільнення працівників DOT

Якщо цю функцію ввімкнено, середовище виконання може генерувати графічні представлення у форматі DOT за допомогою gst_debug_bin_to_dot_file_with_ts(...) і зберігати їх у визначеній теці.

Інструкція з усунення несправностей (для робочого середовища)

  1. Відтворіть конвеєр: Graph::describe_backend() або last_pipeline().
  2. Збережіть звіт: MeasureReport::to_text() або NeatError::report().
  3. Увімкніть цілеспрямовані зондування:
    • SIMA_GST_BOUNDARY_PROBES=1 для локалізації зони застою.
    • SIMA_GST_ELEMENT_TIMINGS=1 для встановлення часу для кожного елемента.
    • SIMA_GST_FLOW_DEBUG=1 для лічильників потоку для кожного елемента.
  4. Генеруйте DOT-графіки: встановіть SIMA_GST_DOT_DIR і повторіть процес.
  5. Посильте перевірку: SIMA_GST_ENFORCE_NAMES=1 та здійсніть перевірку тайм-аутів для попередніх роликів.

Обробка вихідних даних

Виконання команди Run::pull() дає Sample, який може містити:

  • корисне навантаження у вигляді Tensor (тип зразка: SampleKind::Tensor)
  • набір із кількох результатів (SampleKind::Bundle)

Використовуйте Run::pull_tensors(...) для процесів, орієнтованих на машинне навчання, коли вам потрібні лише тензорні дані, а не повний обсяг даних Sample.

Серіалізація конвеєра (збереження/завантаження).

Конвеєри можна зберігати та відновлювати у форматі JSON:

  • Graph::save(path) зберігає версію JSON, що містить інформацію про тип/мітку/фрагмент/елементи вузлів графа.
  • Graph::load(path) відновлює вузли за допомогою обгортки ConfiguredNode.

Поточна схема навмисно максимально проста та відтворювана, і згодом її можна буде розширити, додавши більше параметрів для вузлів. Крім того, це слугує основою для майбутніх інтеграцій та інструментів.

Інструменти для покращення користувацького досвіду.

  • Graph::describe() використовує GraphPrinter для створення списку вузлів, який легко читається людиною.
  • Graph::describe_backend() повертає рядок gst-launch, який можна використовувати для швидкої відлагодки.

Найменування елементів і детермінізм.

Детерміновані імена елементів є одним із ключових принципів проєктування, оскільки вони забезпечують:

  • gst_bin_get_by_name() для раковин та основних елементів.
  • стабільне кріплення зонда
  • стабільна діагностика та відтворюваність
  • необов’язкове застосування правил іменування («кожен елемент належить до певного вузла»)

Автори модулів повинні забезпечити:

  • фрагменти містять стабільні поля name=, коли необхідно забезпечити можливість отримання доступу до елементів.
  • element_names() повертає кожну явно визначену назву елемента, яку створює фрагмент.
  • оголошення та посилання на іменовані блоки залишаються синхронізованими.

Цілісність імен є частиною build() і не залежить від попереднього виклику validate(). Імена є унікальними в межах одного матеріалізованого сегмента конвеєра, оскільки в рамках структури для пошуку використовуються рекурсивні короткі імена. Окремо оброблені з’єднані сегменти можуть повторно використовувати одне й те саме ім’я. Структура відхиляє конфлікти замість їх перейменування, оскільки імена можуть брати участь у виразах для заповнення та маршрутизації.

З’єднані сегменти, що залежать від вхідних даних, можуть бути матеріалізовані на першому вході. Тому їхня помилка під час створення фіксується під час першого push() або pull(), при цьому оригінальний GraphReport зберігається.


Найменування та підключення етапів

Тепер у фреймворку JSON-файли плагінів розглядаються як дані, що належать плагіну, і під час створення конвеєра він не переписує та не перевіряє окремі поля JSON для кожної стадії.

Налаштування джерела істини:

  1. Детерміновані імена елементів GStreamer, отримані з фрагментів вузлів.
  2. stage-id на елементах шляху моделі SIMA.
  3. sima.model.manifest.v1 – контекст для пошуку статичного контракту/тензора на певному етапі.

Наслідки:

  • Відтепер node_name / input_buffers[*].name / buffers.input[*].name більше не змінюватимуться.
  • Тепер система Build не виконує перевірки з’єднань на основі JSON.
  • Функція перетворення назв все ще застосовується лише до назв елементів.

Для керування виконанням графа моделлю, визначення етапів залежить від stage-id + контексту маніфесту. Для виконання графа, яким не керує модель, явні властивості плагінів є основним елементом керування в середовищі виконання.

Перевірка та контракти

Перевірка потрібна для виявлення проблем на більш ранніх етапах, ніж під час роботи програми:

  • validate() може аналізувати та виконувати попередній прокрут (у стані ПАУЗИ), щоб виявляти моменти зупинки переговорів.
  • contracts/ містить структуровані валідатори для перевірки «правильності роботи конвеєра».

Обов’язкові остаточні перевірки назви перед запуском також виконуються у звичайному процесі збірки. ValidateOptions контролює додаткові етапи перевірки, але не визначає, чи забезпечується цілісність назви.

Для пов’язаних графів validate() компілює топологію кінцевих точок, але не створює рядки для запуску для сегментів, що залежать від вхідних даних. Кожен сегмент проходить обов’язкову перевірку, коли доступний його фактичний вхідний контракт і сегмент матеріалізується.

Очікувана поведінка:

  • під час виконання програми, у разі виникнення критичних помилок, генеруються винятки.
  • процеси перевірки повертають структуровані звіти (зручні для використання в системах безперервної інтеграції).

Вирішення проблем, пов’язаних із контрактом SSD BoxDecode.

Пакети моделей SSD перевіряються на відповідність приватному реєстру точних контрактів для обробки даних після операції на голові під час компіляції графа. Розв’язувач порівнює кожну впорядковану логічну локалізацію та форму H/W/C, а також рівень впевненості; він не сортує рівні, не використовує назви моделей і не приймає загальну альтернативу, подібну до SSD. Наразі зареєстровані рецепти: SSD300-v1, SSD-Mobile-300-v1, SSD-Mobile-320-v1 і SSDlite-Mobile-320-v1.

Вирішений рецепт містить інформацію про активацію оцінки, порядок каналів впевненості, фоновий клас, дозволений вибір класу, необхідний розмір моделі 300x300 або 320x320 і попередню обробку Stretch. Основна частина зберігає рецепт як внутрішній SsdRecipeId; тип декодування публічного та плагінного ABI залишається BoxDecodeType::Ssd / ssd, що є токеном, який підтримується розгорнутим об’єктним декодером. Непідтримувана або неправильна геометрія, конфліктна активація, недійсний вибір класу, відсутність попередньої обробки Stretch або неправильний розмір моделі призводять до помилки до запуску конвеєра. Пошук рецепту відбувається лише під час компіляції та не додає жодних додаткових обчислень для кожного кадру.

Режим роботи сервера RTSP.

run_rtsp() використовує gst-rtsp-server:

  • сервер працює в окремому потоці з основним циклом GLib.
  • у розділі media-configure код знаходить appsrc за назвою та налаштовує параметри/властивості.
  • кадри періодично надсилаються (на основі таймера) з чітко вказаними мітками часу.

Кожен клієнт може отримати власний екземпляр медіафайлу, залежно від конфігурації фабрики.

Налаштування середовища / параметри конфігурації

Середовище виконання підтримує параметри налагодження, які залежать від середовища:

  • SIMA_GST_DOT_DIR – створюйте DOT-файли, що містять графічне представлення (граф) інформації про помилки / для налагодження.
  • SIMA_GST_BOUNDARY_PROBES – увімкнути лічильники потоку на межі.
  • SIMA_GST_STAGE_TIMINGS – увімкнути функцію вимірювання часу для окремих етапів.
  • SIMA_GST_ELEMENT_TIMINGS – увімкнути інструменти для вимірювання часу роботи елементів.
  • SIMA_GST_FLOW_DEBUG – увімкнути лічильники потоку для кожного елемента.
  • SIMA_GST_ENFORCE_NAMES – забезпечує дотримання правил іменування.
  • SIMA_GST_RUN_INPUT_TIMEOUT_MS – час очікування вхідних даних для шляхів, що використовуються під час виконання/збірки.
  • SIMA_GST_VALIDATE_TIMEOUT_MS – час очікування для перевірки перед початком відтворення.
  • SIMA_GST_VALIDATE_INSERT_BOUNDARIES -- вставляйте межі під час виконання функції validate()
  • SIMA_GST_RUN_INSERT_BOUNDARIES – вставляйте межі під час збірки/виконання().
  • SIMA_GST_TEARDOWN_TIMEOUT_MS – час очікування переходу в стан NULL (в мілісекундах).
  • SIMA_GST_TEARDOWN_REAPER_MS – інтервал повторних спроб для reaper (мілісекунди).
  • SIMA_GST_TEARDOWN_ASYNC – пропустити очікування, передати завдання програмі reaper.

Ці параметри навмисно винесені за межі публічного API, щоб ви могли вмикати їх у системах безперервної інтеграції або безпосередньо в робочому середовищі, не перекомпілюючи код. У src/pipeline/internal/* є додаткові низькорівневі прапори налагодження (журналування вхідного потоку, виведення зразків даних, налагодження пулу). Не включайте їх у документацію для користувачів, якщо тільки вам не потрібна глибока діагностика.

Межа середовища виконання хоста PCIe.

Окремо запакований API хоста PCIe має два публічні рівні:

  • pcie::Model — це зручний API, сумісний із вихідним кодом, для однієї моделі.
  • pcie::Runtime — це координатор, що працює з кількома моделями в межах однієї картки, і призначений для підтримки тонкого адаптера OAAX C ABI.

Середовище виконання надає ідентифікатори логічної моделі, ідентифікатори запитів, надані програмою-клієнтом, неблокуюче додавання в чергу, отримання даних з будь-якої моделі, пакетне завантаження, незалежне вивантаження та ідемпотентне очищення. Ідентифікатори апаратних черг залишаються деталлю реалізації. Поточна Modalix реалізація призначає рівно одну завантажену модель кожному з чотирьох черг PCIe і продовжує передавати архіви моделей через віртуальний канал керування Ethernet SSH/SCP.

Для кореляції запитів на виведення використовується підписаний 32-бітний ідентифікатор запиту OAAX, закодований у GstSimaHostMeta.frame-id у процесі обміну даними через PCIe/картку. Бітовий шаблон є незрозумілим і має бути відновлений без змін у загальнодоступному завершенні. Середовище виконання зберігає реєстр відображення моделі на чергу та агрегує результати кожної черги; на стороні картки pcie-pipeline-builder залишається одним процесом і однією моделлю графа для кожної черги.

Транспортна карта містить окремий приватний токен запиту, який має назву, що використовувалася раніше. GstSimaMeta.pcie-buffer-id поле. Воно ідентифікує точний запит драйвера та поточний кредит; звичайні плагіни можуть передавати його без змін, але не повинні перевіряти або змінювати його. stream-id залишається ключем для визначення шляху виведення, а frame-id залишається ключем кореляції застосунку. Лише neatpciesink обробляє запитний токен. У разі успішного виконання повертається відповідь у форматі DATA. У разі відхилення декодера, очищення, перезапуску або збою в нижній частині системи повертається відповідна NEAT_PCIE_FRAME_RETURN_ERROR, що звільняє той самий ресурс хоста та завершує роботу відповідного конвеєра хоста, видаючи повідомлення про помилку, яке можна використати для усунення проблеми, замість того, щоб просто заблокувати його.

Стандартизований OAAX runtime_* Символи C визначають межу адаптера над цим вихідним API. Правила володіння OAAX, коди стану та сховище останньої помилки мають знаходитися в цьому адаптері, а не в API C++.

Як розширити бібліотеку

Додавання нового вузла

  1. Створіть заголовок у файлі include/nodes/<category>/<YourNode>.h.

  2. Реалізуйте в src/nodes/<category>/<YourNode>.cpp.

  3. Переконайтеся:

    • backend_fragment(i) є дійсним і детермінованим.
    • усі важливі елементи мають назви, і їх повертає функція element_names(i).
  4. Додайте тести (в ідеалі, один із таких):

    • аналіз/перевірка тестів
    • запустіть/виконайте тести за допомогою простого конвеєра, що обробляє вхідні та вихідні дані.

Додавання діагностичних інструментів для середовища виконання.

  • Рекомендується додавати поля до DiagCtx та GraphReport.
  • Якщо оновлення відбуваються в потоках, що здійснюють потокову передачу даних, використовуйте атомарні операції (або інший механізм, який не потребує блокування).
  • Перетворіть на звичайні типи знімків для створення звітів.

Правила залежностей (не підлягають обговоренню)

  • builder/ не повинен залежати від GStreamer або pipeline/.
  • gst/ не повинен залежати від pipeline/.
  • nodes/ не повинні залежати від pipeline/ (вузли – це описи, що створюються під час компіляції, а не інструменти оркестрування, які використовуються під час виконання).
  • pipeline/ є головним координатором і може використовувати gst/, builder/, nodes/, contracts/, policy/, а також внутрішні компоненти моделі.

Це забезпечує модульність архітектури та запобігає виникненню циклічних залежностей.

Тести та приклади

  • examples/ демонструють типові сценарії використання в повному циклі:

    • декодувати RTSP
    • запустити архів моделі
    • запустіть сервер RTSP
  • tests/ перевіряють важливі аспекти функціонування:

    • шляхи для читання файлів
    • еквівалентність розширення групи (вхідні групи)
    • шлях збереження тензора + повний цикл збереження/завантаження
    • model_resnet50_multi_test перевіряє точність моделі, використовуючи декілька екземплярів графа/запуску.

Під час додавання нових функцій, насамперед додавайте тести, які:

  • відтворюйте рядок конвеєра детерміновано.
  • перевірте обґрунтованість припущень щодо узгодження щодо максимальних обсягів
  • забезпечте, щоб у разі виникнення помилок створювалися корисні діагностичні звіти у вигляді GraphReport.

Захист від випадкових змін у документах.

Забезпечте узгодженість документації та коду:

  • Якщо ви змінюєте загальнодоступні заголовки (include/*), оновіть файл README + архітектура.
  • Якщо ви зміните стандартний тестовий конвеєр виробництва. (tests/e2e_pipelines/obj_detection/sync_yolov8_test.cpp), оновіть обидві документації.
  • Якщо ви додаєте нові параметри середовища, додайте їх до розділу «Параметри середовища/конфігурації».

Принципи проєктування.

  1. Детермінізм перемагає

    • стабільні назви елементів, стабільні рядки конвеєра, стабільні звіти.
  2. Можливість налагодження є пріоритетною

    • журнали роботи автобусів, дані DOT, зонди для визначення меж, чіткі інструкції щодо відтворення проблеми.
  3. Безпечна паралельність

    • потоки для потокового збору даних перевіряють лише атомарні операції (знімки створюють звичайні звіти).
  4. Ніколи не призупиняйте процес.

    • процес видалення має бути безпечним; слід уникати ситуацій, коли через несправні модулі плагінів система блокується на невизначений термін.
  5. Забезпечте стабільність публічного API

    • внутрішні рефакторинги не повинні призводити до помилок у коді користувача, якщо тільки це не зроблено навмисно в рамках контролю версій.