К содержимому
MoranaLabs
R&D — сколько камер тянет одна коробка

Бюджет FPS многопоточного узла 

Тринадцать триллионов операций в секунду звучат так, будто камер поместится сколько угодно. По нашей модели на профиле 1080p25 с детекцией каждого кадра узел обслуживает три камеры, а первым в потолок упирается не процессор и не шина, а очередь к единственному ускорителю. Работа объясняет, откуда берется это число, и дает протокол, который проверяет его за один день на стенде.

в работе

модель и протокол готовы, стендовый прогон на 1/2/4/8 потоков запланирован

программа открыта 13.08.2026

стек и предметная область
  • raspberry pi 5 + hailo-8l
  • gstreamer / ffmpeg
  • теория массового обслуживания
  • usl, kingman, little
  • rc-модель нагрева
  • дискретно-событийное моделирование
аннотация

Работа отвечает на вопрос, который заказчик задает на третьей минуте первого созвона: сколько камер обслужит один edge-узел. Показано, почему на него не отвечает ни один даташит, и что слово FPS обозначает семь разных величин, отличающихся на порядок. Конвейер разобран по восьми стадиям с указанием ресурса, который каждая занимает; отдельно разобран отчет компилятора по нашей сборке детектора и разрыв в три с половиной раза между оценкой инструмента (315 кадров в секунду) и живым замером на железе (80–90). Аппарат — операционные законы, теорема Пальма — Хинчина о суперпозиции потоков, приближение Кингмана, универсальный закон масштабируемости и одноемкостная тепловая модель. Из них собрана модель бюджета из четырех потолков, посчитаны предсказания для одного, двух, четырех и восьми потоков и цена прогрева корпуса. Практическая часть — протокол замера на один рабочий день с кодом стенда, критериями отказа и списком двенадцати способов обмануть себя при измерении производительности. Собственного многопоточного замера у лаборатории пока нет, и ни одно число в тексте за него не выдается.

ключевые слова
  • edge-инференс
  • бюджет FPS
  • многопоточная видеоаналитика
  • теория массового обслуживания
  • универсальный закон масштабируемости
  • тепловой троттлинг
  • Hailo-8L
  • Raspberry Pi 5
паспорт работы
объем
7 частей, 28 глав
источников
72, из них 8 — материалы производителей
формул
20 со сквозной нумерацией
рисунков
6 плюс два интерактивных стенда
своих замеров
один, на одной камере; многопоточный прогон запланирован
срез
13.08.2026

Ссылки вида [12] в тексте ведут в список литературы. Формулы пронумерованы сквозной нумерацией.

кратко

Если читать работу целиком некогда

01

Почему даташит не отвечает

Производитель ускорителя меряет свою деталь, производитель одноплатника — свою, а заказчик покупает систему, в которой к ним добавлены декодирование восьми потоков, масштабирование каждого кадра, передача по шине, трекер и герметичный корпус на солнечной стороне. Вместе эти строки стоят дороже, чем сам инференс, и ни одна из них не входит в паспортную цифру.

02

Четыре потолка вместо одного

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

03

Протокол дешевле спора

Модель без замера — кривая с неизвестным масштабом, замер без модели — одна точка. Вместе они дают предсказание для конфигураций, которых на стенде не было. Протокол написан до прогона намеренно: методика, придуманная после знакомства с числами, всегда объясняет ровно эти числа.

факты
формат
длинная форма: 7 частей, 28 глав, глоссарий и библиография
источники
72 позиции: от Литтла 1961 и Пальма 1943 до документации Raspberry Pi и Hailo
свой замер
80–90 к/с на одной камере, Hailo-8L; условия того замера записаны не полностью
оценка компилятора
315 к/с по сумме времен пяти контекстов нашей сборки — расчет инструмента
разрыв
3,5 раза между оценкой и живым замером, и он весь состоит из того, за что платит заказчик
трафик по шине
2,32 МБ на каждую детекцию: 1,23 МБ входа и 1,09 МБ выхода
потолок по шине
около 172 детекций/с на PCIe Gen 2 и 345 на Gen 3 — расчет
цена прогрева
20 % темпа в закрытом корпусе, что равно одной камере из шести — расчет
главный рычаг
децимация: бьет по всем четырем потолкам сразу и стоит ноль рублей
проверяемых гипотез
4, с назначенными заранее порогами закрытия
стоимость проверки
один рабочий день на собранном стенде
Часть I

Вопрос, которого нет в даташите

Заказчик спрашивает про камеры, производитель отвечает про операции в секунду, интегратор показывает ролик с одной камерой. Три разных языка, между которыми нет словаря. Часть строит этот словарь: разбирает, какие семь величин прячутся за словом FPS, что физически стоит на столе и что именно было и не было зафиксировано в нашем собственном замере.

глава 1

Один вопрос, от которого зависит вся смета

Пока на него нет числа, коммерческое предложение — это гадание с точностью до порядка

Разговор с техническим заказчиком по видеоаналитике идет по одному сценарию. Сначала выясняется задача: считать людей, ловить нарушение зоны, находить дрон, проверять каску. Потом — где стоят камеры и сколько их. И на третьей минуте звучит вопрос, ради которого созвон и был назначен: сколько таких камер потянет одна коробка. От ответа зависит не точность модели и не красота интерфейса, а число узлов на объекте, длина кабельных трасс, количество мест в шкафу, класс источника бесперебойного питания и итоговая цифра в смете. Ошибка в этом числе в два раза меняет проект целиком.

Честный ответ подрядчика в этот момент обычно звучит как «на пилоте померим». Он честный, но бесполезный: пилот идет месяц, а цифру надо назвать сегодня. Нечестный ответ звучит увереннее и берется из даташита ускорителя: тринадцать триллионов операций в секунду, модель весит три гигаоперации на кадр, делим одно на другое, получаем четыре тысячи кадров в секунду, значит камер поместится сколько угодно. Это арифметика уровня «автомобиль с мотором в двести лошадиных сил проедет двести километров за час»: величины настоящие, связь между ними выдуманная.

Причина, по которой на этот вопрос не отвечает ни один даташит, простая. Производитель ускорителя измеряет свою деталь: сколько раз в секунду кремний прогонит через себя готовый тензор. Производитель одноплатника измеряет свою: частоту ядер и пропускную способность памяти. Заказчик покупает не деталь, а систему, в которой к этим двум деталям добавлены декодирование восьми потоков H.264, масштабирование каждого кадра, копирование по шине, разбор выходов детектора, трекер, запись клипов на карту памяти, отправка событий по сети и герметичный корпус на солнечной стороне здания. Ни одна из этих строк не входит в паспортную цифру, и вместе они стоят дороже, чем сам инференс.

Дальше в тексте показано, что на нашем железе первым в потолок упирается не то, что называют в презентациях. Не «мощность нейросети» и не «слабый процессор» — а последовательность, в которой единственный ускоритель обслуживает очередь из нескольких камер, и тепловой контур закрытого корпуса, который отбирает у этой очереди пятую часть темпа через двенадцать минут работы. Оба эффекта считаются заранее, оба проверяются за день, и оба переводятся в число камер и в рубли.

СКОЛЬКО КАМЕР РАЗРЕШАЕТ КАЖДЫЙ РЕСУРС ПО ОТДЕЛЬНОСТИускоритель3,613 TOPS, одна очередьядра12,94 × A76, декод и препроцессшина6,9PCIe Gen2 x1тепло4,8закрытый корпусИТОГ = МИНИМУМРАСЧЕТ ПО ФОРМУЛЕ (12) ДЛЯ 1080p25, ДЕТЕКЦИЯ КАЖДОГО КАДРА, СБОРКА 640×640, PCIe Gen2
Рис. 1. Четыре независимых ограничения узла, каждое в одних и тех же единицах — «сколько камер разрешает». Итоговое число всегда равно минимальному из четырех, поэтому улучшение любого ресурса, кроме самого узкого, не дает ничего. Значения на диаграмме — расчет по модели из части IV для профиля 1080p25 с детекцией каждого кадра.
глава 2

Семь величин, которые называют одним словом «FPS»

Подмена определения дает расхождение в пять–десять раз без единой ошибки в арифметике

Прежде чем что-то измерять, надо договориться, что именно. Слово «кадров в секунду» в разговоре о видеоаналитике обозначает семь разных величин, и они отличаются друг от друга не на проценты, а в разы. Ниже — все семь, в порядке от самой лестной для продавца до самой полезной для заказчика.

паспортная
производительность ускорителя из даташита или из отчета компилятора: сколько раз в секунду кремний способен прогнать сеть при идеальной подаче данных. Не включает ни декодирование, ни подготовку тензора, ни разбор выходов, ни то, что источников несколько.
синтетическая
результат прогона утилиты производителя на заранее подготовленном буфере в памяти. Ближе к реальности, чем паспортная, но входные данные лежат готовыми, а конкурентов за шину нет.
пиковая сквозная
то, что показывает демонстрационный ролик: холодный узел, одна камера, минута работы. Самое частое число в коммерческих предложениях и самое бесполезное в проектировании.
устойчивая сквозная
то же самое после теплового выхода на режим, на сцене с реальной сложностью и с полным конвейером. Ниже пиковой на десятки процентов, и именно она должна попадать в договор.
частота источника
сколько кадров в секунду отдает камера. Величина внешняя: узел не может выдать больше, но обязан либо обработать, либо осознанно и предсказуемо выбросить каждый кадр.
детекционная
сколько раз в секунду по каждому потоку реально вызывается детектор. При децимации в два раза она вдвое ниже частоты источника, и на качество слежения это влияет куда меньше, чем принято думать.
полезная (goodput)
сколько кадров дошло до логики принятия решения и повлияло на события. Кадр, который декодировали и выбросили из переполненной очереди, из этой величины выпадает, хотя процессорное время на него уже потрачено.

Разрыв между первой и последней строкой на реальном железе достигает порядка. Наш собственный случай разобран в главе 4 и в главе 12: отчет компилятора для сборки детектора обещает 315 кадров в секунду, живой замер на одной камере дал 80–90, а после перехода к нескольким потокам и прогрева корпуса устойчивая цифра будет еще ниже. Ни одно из этих чисел не ложь — они просто измеряют разные вещи. Ложь появляется в момент, когда первое число называют в ответ на вопрос про седьмое.

f_det = f_src / k, G = f_det · (1 − p_loss)

где f_src — частота источника, к/с; k — коэффициент децимации (детектор вызывается на каждом k-м кадре); f_det — детекционная частота; p_loss — доля кадров, потерянных в очередях; G — полезная частота, goodput

(1)
Два управляемых параметра здесь ровно два: k, который выбирает инженер, и p_loss, который выбирает физика, если инженер не оставил запаса. Все остальное в формуле задано снаружи. Практический вывод из нее делается в главе 17: децимация — единственный рычаг, который меняет все четыре потолка узла одновременно и стоит ноль рублей.
глава 3

Что физически стоит на столе

Паспорт узла: четыре ядра, один ускоритель, одна линия шины, один тепловой контур

Узел, о котором идет речь, — Raspberry Pi 5 с модулем ускорителя на Hailo-8L, подключенным по единственной линии PCIe. Это та же связка, на которой собран детектор малоразмерных целей направления Falcon Eye, и та же, которую мы предлагаем заказчикам как нижнюю ступень линейки. Ее паспортные свойства опубликованы и проверяемы, поэтому начинать надо с них.

узелзначениеисточник
процессорBCM2712, четыре ядра Cortex-A76, 2,4 ГГцматериал производителя [41]
декодирование видеоаппаратный блок HEVC 4Kp60; аппаратного декодера H.264 нетматериал производителя [41]
ускорительHailo-8L, 13 TOPS в INT8, без внешней DRAMматериал производителя [44, 45]
типовое потребление ускорителя1,5 Втматериал производителя [44]
шина к ускорителюодна линия PCIe; в комплекте AI HAT+ линия переводится в режим Gen 3материал производителя [42, 43]
тепловые пороги80 °C — прогрессивное снижение частоты, 85 °C — жесткий потолокматериал производителя [40]
питание5 В, 5 А (25 Вт); в режиме 15 Вт лимит периферии 600 мАматериал производителя [40]
Паспорт узла. Все строки взяты из документации производителей и ничем не дополнены. Обратите внимание на вторую: она единственная в таблице, которая обычно становится сюрпризом, и она же определяет половину поведения узла под многопоточной нагрузкой.

Из этой таблицы сразу следуют три вещи, которые дальше будут работать как ограничения модели. Первое: ускоритель один. Сколько бы потоков ни пришло, они выстроятся в общую очередь к одному устройству, и это очередь с последовательным обслуживанием — глава 11 показывает, чем такая очередь отличается от четырех независимых. Второе: линия PCIe одна, и через нее в обе стороны едут граничные тензоры каждого кадра — глава 9 считает, сколько это в мегабайтах в секунду и когда упирается. Третье: тепловой контур общий. Ядра, ускоритель и накопитель греют один и тот же объем воздуха внутри корпуса, а порог снижения частоты назначен производителем и понижается пользователем, но не повышается [40].

Отдельно стоит сказать про то, чего в паспорте нет и не будет: конструктива. Тепловое сопротивление корпуса, наличие обдува, ориентация платы, температура в шкафу и солнечная сторона стены не описаны ни в одном документе, а влияют на устойчивую производительность сильнее, чем выбор между двумя близкими моделями детектора. Часть III переводит это в формулу с двумя параметрами, которые снимаются с кривой разогрева за один прогон.

глава 4

Наш собственный замер и то, чего в нем не записано

80–90 кадров в секунду на одной камере — цифра настоящая, протокол за ней неполный

На живом железе мы этот узел уже мерили. Сборка детектора БПЛА под Hailo-8L дала 80–90 кадров в секунду при целевом профиле 60 — то есть профиль был перекрыт с запасом. Замер стендовый: одна камера, узел на столе. Эта цифра опубликована на странице направления Falcon Eye и используется в коммерческих разговорах как ориентир.

Теперь неприятная часть, с которой и начинается настоящая работа. В журнале направления зафиксирована сама цифра и профиль сборки, но не полный набор условий: сколько длилось окно измерения, какая была температура кристалла к его концу, входило ли в измеряемый интервал декодирование, считался ли постпроцессинг, какой был режим линии PCIe. Для ответа на вопрос «перекрыли ли мы шестьдесят» этого достаточно. Для ответа на вопрос «сколько камер поместится на объекте» — нет: неизвестно, какую именно из семи величин главы 2 мы измерили.

Второй источник собственных данных — отчет компилятора Hailo по нашей сборке. Он устроен подробнее, чем принято думать: для сети YOLO11n в разрешении 640×640 под Hailo-8L он дает разложение на пять контекстов, время каждого, объемы граничных и межконтекстных тензоров, коэффициенты использования вычислительных блоков и распределение весов по уровням памяти. Из него считается верхняя граница производительности ускорителя — 315 кадров в секунду, и он же показывает, что загрузка умножителей в среднем по контекстам держится около 0,11 от пиковой. Разбору этого отчета посвящена глава 12: разрыв между 315 и 90 — самая содержательная величина во всей работе, потому что он весь состоит из вещей, за которые платит заказчик.

величиназначениеоткуда
живой замер, одна камера80–90 к/снаш стенд, июнь 2026
оценка компилятора, сумма по контекстам315 к/сотчет DFC по нашей сборке
контекстов в сборке5отчет DFC
операций на кадр6,38 GOPs / 3,21 GMACsотчет DFC
параметров модели3,38 млнотчет DFC
граничный вход / выход1 228 800 Б / 1 092 000 Ботчет DFC
межконтекстный трафик2 944 800 Б на кадр, портов DDR — 0отчет DFC
средняя загрузка умножителей0,11 от пиковойотчет DFC
Все, что у нас есть по этому узлу на сегодня. Первая строка — измерение, остальные — выкладки инструмента компиляции, то есть расчет, а не замер. Именно так они и используются дальше: как параметры модели, а не как доказательства.

Работа дальше устроена так. Часть II разбирает конвейер по стадиям и показывает, где именно расходуется время и какой ресурс каждая стадия занимает. Часть III дает аппарат: закон Литтла, универсальный закон масштабируемости, формулу Кингмана и тепловую RC-модель — этого хватает, чтобы предсказать поведение узла на N потоках. Часть IV собирает из этого модель бюджета и считает предсказания для одного, двух, четырех и восьми потоков. Часть V — протокол суточного замера с кодом стенда, который эти предсказания проверит или опровергнет. Часть VI переводит результат в смету. Часть VII перечисляет границы и то, что мы обязуемся опубликовать после прогона, включая случай, когда модель окажется неверной.

Часть II

Анатомия конвейера

Кадр проходит восемь стадий и четырех разных исполнителей: ядра процессора, аппаратный блок декодера, шину и ускоритель. Стоимость каждой стадии считается в разных единицах, и складывать их напрямую нельзя. Часть проходит путь кадра целиком и на каждой стадии отвечает на два вопроса: сколько это стоит и что произойдет, когда потоков станет восемь.

глава 5

Путь одного кадра

Восемь стадий, четыре исполнителя, три очереди — и только одна из стадий видна в даташите

Инференс — это одна восьмая часть пути. Остальные семь никто не рекламирует, потому что они одинаковы у всех и не содержат ничего впечатляющего. При этом на многопоточной нагрузке именно они определяют, где узел встанет.

ПУТЬ ОДНОГО КАДРА: ВОСЕМЬ СТАДИЙ, ЧЕТЫРЕ РАЗНЫХ ИСПОЛНИТЕЛЯRTP/RTSPядро ОСдепакетизация1 поток CPUдекодированиеCPU или блок HEVCмасштаб и поляCPU / NEONшина PCIeDMAинференсускорительNMSчип / CPUтрекер и логикаCPUОЧЕРЕДИкадрытензорызаявкиКРАСНЫМ — СТАДИИ, КОТОРЫЕ ПРИ N ПОТОКАХ КОНКУРИРУЮТ ЗА ОДИН И ТОТ ЖЕ РЕСУРСДЕКОД И ПРЕПРОЦЕССИНГ ДЕЛЯТ ЧЕТЫРЕ ЯДРА, ШИНА И УСКОРИТЕЛЬ СУЩЕСТВУЮТ В ЕДИНСТВЕННОМ ЧИСЛЕОБЩИЙ ТЕМП ЗАДАЕТ САМАЯ МЕДЛЕННАЯ ИЗ НИХ, А НЕ СРЕДНЕЕ ПО КОНВЕЙЕРУ
Рис. 2. Конвейер обработки одного потока. Красным отмечены стадии, которые при N камерах конкурируют за один и тот же физический ресурс: декодирование и препроцессинг делят четыре ядра, шина и ускоритель существуют в единственном экземпляре. Между стадиями стоят очереди — именно в них, а не в самих стадиях, живет разница между «работает» и «сыпется».

Формально время обработки кадра — сумма времен стадий. Практически из этой суммы нельзя получить пропускную способность, потому что стадии выполняются на разных устройствах и частично параллельно: пока ускоритель считает кадр номер сто, ядра декодируют сто первый. Правильная модель конвейера — не сумма, а максимум по загруженности ресурсов, и это первое место, где интуиция обычно подводит.

T_lat = Σ t_i (задержка), F_max = 1 / max_r ( Σ_{i∈r} t_i ) (пропускная способность)

где t_i — время i-й стадии; r — физический ресурс (ядра, блок декодера, шина, ускоритель); внутренняя сумма берется по стадиям, которые исполняет ресурс r

(2)
Задержка складывается, пропускная способность — нет. Ускорение стадии, которая не принадлежит самому загруженному ресурсу, уменьшит задержку и не изменит FPS ни на кадр. Это прямое следствие операционного анализа систем массового обслуживания [13, 14] и причина, по которой оптимизация «на глаз» так часто не дает ничего.

Отсюда же — рабочий метод поиска узкого места, известный как USE: для каждого ресурса смотреть загрузку, насыщение и ошибки, а не искать «медленный код» [72]. На нашем узле ресурсов ровно четыре: ядра, аппаратный декодер, линия PCIe и ускоритель. Пятым ограничением работает тепловой контур, который не является ресурсом в обычном смысле, но ведет себя как ресурс с медленной обратной связью, — ему посвящена глава 15.

глава 6

Прием потока: сеть отдает кадры не так ровно, как кажется

Камера обещает 25 к/с, но приходят они пачками — и это меняет требования к буферам

Видеопоток приходит по RTSP поверх RTP [32, 33, 34]. На уровне протокола кадр — это несколько пакетов, собираемых в единицу доступа; на уровне сети между камерой и узлом стоят коммутатор, иногда радиомост, иногда чужой канал с чужим трафиком. Даже если камера отдает строго по таймеру, до узла кадры доезжают с джиттером, а на загруженном канале — группами.

Отсюда два практических следствия. Первое: приемный буфер обязан быть, и его глубина — проектный параметр, а не значение по умолчанию из библиотеки. Второе: буфер не может быть большим. Раздутые буферы дают ровно тот эффект, который в сетях описан как bufferbloat [25]: очередь перестает терять пакеты, но начинает копить задержку, и система, формально не потерявшая ни кадра, выдает события с секундным опозданием. Для видеоаналитики это хуже потери: пропущенный кадр незаметен, а событие, пришедшее через полторы секунды после того, как человек прошел через зону, обесценивает систему.

Третье следствие — про измерения. Счетчик кадров на входе конвейера меряет камеру, а не узел. Если камера отдает 25 к/с, а узел успевает 12, вход все равно покажет 25: разница уйдет в потери на следующей стадии. Поэтому в протоколе части V точка съема частоты стоит на выходе конвейера, а на входе считается только приход и потери.

глава 7

Декодирование: развилка, которая стоит половины узла

На Raspberry Pi 5 нет аппаратного H.264 — и это решает больше, чем выбор модели детектора

В BCM2712 остался единственный аппаратный декодер — HEVC до 4Kp60. Блоков для H.264 на кристалле нет [41]. Логика производителя понятна и в целом верна: четыре ядра A76 разбирают H.264 быстрее, чем это делал старый аппаратный блок предыдущего поколения. Для настольного применения это улучшение. Для узла видеоаналитики с восемью камерами — смена статьи расходов: работа, которая раньше выполнялась бесплатно с точки зрения процессора, теперь конкурирует за те же ядра, на которых живут препроцессинг, трекер и бизнес-логика.

Цена декодирования зависит от кодека, разрешения, битрейта и структуры группы кадров. Ключевая асимметрия: опорный кадр стоит в несколько раз дороже предсказанного, поскольку декодируется целиком, без опоры на предыдущий [35, 38]. При типовой структуре с опорным кадром раз в две секунды это означает регулярный всплеск нагрузки на всех камерах сразу — и всплески эти не синхронизированы между потоками, что дает именно тот рваный профиль, который разбирается в главе 13.

профиль потокакто декодируетоценка стоимости кадрастатус цифры
H.265 1080pаппаратный блок HEVCпорядка 1 мс процессорного времени на обвязкуоценка, ждет замера
H.264 1080pядра A76единицы миллисекунд на кадроценка, ждет замера
H.264 4Kядра A76первые десятки миллисекунд на кадроценка, ждет замера
H.265 4Kаппаратный блок HEVCзаявлено до 4Kp60 [41]материал производителя
Стоимость декодирования — единственный параметр модели, который мы не можем взять ни из документации, ни из отчета компилятора. Он снимается на стенде за двадцать минут (листинг в главе 21) и после этого перестает быть предметом спора. До этого момента в расчетах он фигурирует как диапазон, а в калькуляторе — как ползунок.

Отдельная ловушка — «просто включить аппаратное ускорение». На узле без аппаратного декодера H.264 попытка запросить его через стандартный интерфейс ядра приводит либо к ошибке, либо к молчаливому откату на программный путь. Второй вариант опаснее: система работает, ядра загружены, а инженер уверен, что декодирование ничего не стоит. Протокол в части V проверяет это явно — сравнением загрузки ядер при пустом конвейере и при конвейере без инференса.

глава 8

Препроцессинг: три копии, о которых никто не помнит

Масштабирование, цветовое пространство и укладка тензора съедают ядра тише всех

Между декодером и ускорителем кадр меняет форму. Декодер отдает изображение в планарном формате с субдискретизацией цвета, детектор ждет тензор фиксированного размера в своем порядке каналов и своем диапазоне значений. Между этими двумя состояниями стоят: приведение цветового пространства, масштабирование с сохранением пропорций и дополнением полями, нормализация и укладка в непрерывный буфер, пригодный для передачи по шине.

Каждая операция сама по себе дешевая, но их три, и каждая — это проход по памяти объемом в мегабайты. Кадр 1080p в планарном формате занимает около 3 МБ, целевой тензор 640×640×3 — 1,23 МБ. Наивная реализация делает три полные копии на кадр; при восьми потоках по 25 к/с это порядка гигабайта в секунду трафика к памяти на одном только препроцессинге. Ядра при этом заняты не вычислениями, а ожиданием памяти — ситуация, которую хорошо описывает крышевая модель [23]: операционная интенсивность у таких стадий низкая, и упираются они в полосу, а не в арифметику.

B_pre ≈ N · f_src · (S_dec + S_rgb + S_tensor) · c

где S_dec — размер декодированного кадра, S_rgb — после приведения цвета, S_tensor — целевого тензора, c — число проходов по каждому буферу (чтение плюс запись), N — число потоков

(3)
Формула нужна не для точности, а для порядка величины: она показывает, что препроцессинг — это задача про полосу памяти, и оптимизируется он устранением копий, а не ускорением арифметики. Практические приемы: масштабирование прямо из формата декодера, передача буферов по ссылке вместо копирования, выравнивание размеров под векторные инструкции.
глава 9

Шина: два с лишним мегабайта на каждый кадр

Одна линия PCIe — это жесткий потолок, который считается за минуту и не двигается

Ускоритель подключен одной линией PCIe. По ней в каждую сторону едут граничные тензоры: на вход — подготовленное изображение, на выход — карты признаков головы детектора. Для нашей сборки отчет компилятора дает точные числа: 1 228 800 байт входа (это ровно 640×640×3) и 1 092 000 байт выхода. В сумме 2,32 МБ на каждую детекцию.

B_bus = N · f_det · (S_in + S_out), N_bus = B_eff / ( f_det · (S_in + S_out) )

где S_in, S_out — граничные тензоры сборки; B_eff — эффективная пропускная способность линии с учетом накладных расходов протокола; N_bus — потолок по числу камер

(4)

Эффективная пропускная способность заметно ниже номинальной: на нее влияют кодирование физического уровня, размер полезной нагрузки транзакции и поведение конкретного контроллера — измерения на реальных системах показывают потери порядка десятков процентов от теоретического потолка [48]. Для оценок берем консервативные значения: около 400 МБ/с для режима Gen 2 и около 800 МБ/с для Gen 3 [47]. При наших размерах тензоров это дает потолок примерно 170 детекций в секунду на Gen 2 и около 345 на Gen 3 — независимо от того, сколько камер их создают.

режим линииэффективная полоса (оценка)потолок детекций/скамер при 25 дет/с
PCIe Gen 2 x1≈ 400 МБ/с≈ 172≈ 6,9
PCIe Gen 3 x1≈ 800 МБ/с≈ 345≈ 13,8
Расчет по формуле (4) при S_in + S_out = 2,32 МБ. Строка Gen 3 — довод в пользу того, чтобы проверять режим линии на каждом узле при вводе в эксплуатацию: комплект AI HAT+ переводит линию в Gen 3 сам [43], а собранный вручную узел на M.2-переходнике может молча остаться на Gen 2 и потерять половину потолка.
глава 10

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

Разбор выходов, подавление немаксимумов, ассоциация, запись клипов, отправка событий

После ускорителя работа не заканчивается. Выходы головы детектора надо превратить в рамки, отсеять перекрывающиеся, связать с существующими треками, применить правила (зона, направление, длительность), при срабатывании записать клип и отправить событие. Все это исполняют те же четыре ядра.

Подавление немаксимумов может выполняться внутри сборки на самом ускорителе — в нашей конфигурации так и сделано. Это заметная экономия процессорного времени и одновременно ограничение: параметры порогов зашиваются в сборку, и менять их на ходу нельзя. Инженерный компромисс здесь решается в пользу чипа, потому что процессорное время на этом узле — самый дефицитный ресурс из четырех.

Трекер — вторая по значимости статья. Классическая связка «фильтр Калмана плюс венгерский алгоритм» [56, 59] стоит доли миллисекунды на кадр при десятке целей и растет квадратично по числу объектов в кадре; варианты с ассоциацией по внешнему виду [57] дороже на порядок, потому что тянут собственную сеть. Для наших задач существенно другое: именно трекер позволяет вызывать детектор не на каждом кадре, и поэтому он не расход, а рычаг экономии — количественно это разобрано в главе 17.

  • Запись клипов на карту памяти: пиковые задержки записи блокируют поток, если запись идет синхронно в том же потоке исполнения.
  • Отправка событий по сети: таймаут недоступного сервера обязан быть коротким, иначе конвейер встает из-за чужой инфраструктуры.
  • Журналирование: подробный лог на каждый кадр — это не только диск, но и блокировки; на восьми потоках он становится заметной статьей.
  • Служебные процессы: обновления, мониторинг, сторожевой таймер — фон, который в пятиминутном замере не виден, а в суточном виден.
Часть III

Почему восемь потоков не равны восьмикратной нагрузке

Здесь собран весь математический аппарат работы. Он старый, проверенный и умещается в пять формул: операционные законы Литтла и Бузена, приближение Кингмана, теорема Пальма — Хинчина о суперпозиции потоков, универсальный закон масштабируемости и одноемкостная тепловая модель. Ничего специфичного для нейросетей в этой части нет — и в этом ее ценность: выводы переносятся на любой edge-узел с одним ускорителем.

глава 11

Операционные законы: что известно до всякого эксперимента

Литтл, закон загрузки и закон узкого места — три соотношения, которые нельзя нарушить

Закон Литтла связывает три величины в любой системе, которая работает в установившемся режиме: среднее число заявок внутри, интенсивность их прихода и среднее время пребывания [1, 2]. Он не требует никаких предположений о распределениях, дисциплине очереди и внутреннем устройстве — только стационарности.

L = λ · W

где L — среднее число кадров, находящихся в конвейере; λ — интенсивность прихода, кадров в секунду; W — среднее время пребывания кадра в конвейере, секунды

(5)
Практическая польза мгновенная. Узел принимает 8 камер по 25 к/с, то есть λ = 200 кадров в секунду. Требование по задержке — 150 мс от кадра до события. Значит, внутри конвейера в среднем живет 30 кадров, и под них нужны буферы, память и гарантия, что ни один из них не потеряется молча. Если по факту в системе оказывается 300 кадров, задержка равна полутора секундам, чем бы ни клялся разработчик.

Второе соотношение — закон загрузки: загрузка ресурса равна произведению пропускной способности системы на требование к этому ресурсу на одну заявку [13, 14]. Третье — закон узкого места: пропускная способность системы не может превысить обратную величину наибольшего требования.

ρ_r = X · D_r ≤ 1 ⟹ X_max = 1 / max_r D_r

где ρ_r — загрузка ресурса r; X — пропускная способность системы, кадров в секунду; D_r — суммарное требование одного кадра к ресурсу r, секунды

(6)
Из этой пары следует правило, которое экономит недели работы: измерять надо не «скорость системы», а требования D_r по каждому из четырех ресурсов узла. После этого пропускная способность считается на бумаге, а любое предложение по оптимизации проверяется до того, как написан код.

Важное ограничение операционного анализа: он дает средние. Средним заказчик не пользуется — его интересует, не опоздает ли событие. Для этого нужен аппарат очередей, и он появится в главе 14. Но полезно понимать порядок: операционные законы верны всегда, приближения теории очередей — при определенных предположениях, а результаты симуляции — только для тех параметров, которые в нее заложены.

глава 12

Ускоритель изнутри: пять контекстов и разрыв в три с половиной раза

315 кадров в секунду по отчету компилятора против 80–90 на живом железе — куда делось остальное

Hailo-8L устроен иначе, чем графический ускоритель. Это не универсальный процессор с внешней памятью, а массив вычислительных блоков с распределенной памятью на кристалле; внешней DRAM у него нет вовсе [44, 45]. Компилятор раскладывает сеть по этому массиву статически: каждый слой получает свои умножители и свои куски памяти под веса и промежуточные данные. Если сеть целиком не помещается, она режется на контексты, которые проходят через чип последовательно.

ОДИН КАДР НА УСКОРИТЕЛЕ: ПЯТЬ КОНТЕКСТОВ И ЧЕТЫРЕ ПЕРЕКЛЮЧЕНИЯ МЕЖДУ НИМИвход1,23Мконтекст 01288 к/сконтекст 11267 к/сконтекст 21497 к/сконтекст 31363 к/сконтекст 44785 к/сСУММА ВРЕМЕН КОНТЕКСТОВ = 3,18 мс → 315 КАДРОВ/С ПО ОЦЕНКЕ КОМПИЛЯТОРАЗАМЕР НА ЖИВОМ ЖЕЛЕЗЕ: 80–90 КАДРОВ/С. РАЗРЫВ В 3,5 РАЗА ЖИВЕТ ВНЕ ЭТОЙ СХЕМЫМЕЖКОНТЕКСТНЫЙ ТРАФИК 2,94 МБ НА КАДР ОСТАЕТСЯ ВНУТРИ ЧИПА: ПОРТОВ DDR В СБОРКЕ НОЛЬНАРУЖУ ПО ШИНЕ ИДУТ ТОЛЬКО ГРАНИЧНЫЕ ТЕНЗОРЫ: 1,23 МБ ВХОДА И 1,09 МБ ВЫХОДАДАННЫЕ — ОТЧЕТ КОМПИЛЯТОРА ПО СБОРКЕ YOLO11n 640×640 ДЛЯ Hailo-8L
Рис. 3. Наша сборка YOLO11n 640×640 под Hailo-8L в разложении компилятора: пять контекстов, их расчетные частоты и объемы тензоров. Сумма времен контекстов дает 3,18 мс на кадр, то есть 315 кадров в секунду как верхнюю оценку самого счета. Живой замер на одной камере — 80–90 кадров в секунду.

Разрыв в три с половиной раза — самая содержательная величина в этой работе. Он складывается из вещей, которых нет в отчете компилятора, и каждая из них проверяема на стенде.

  • Хост-часть кадра: декодирование, приведение формата, укладка тензора, разбор выходов. Это процессорное время, которое в отчете компилятора не учитывается вовсе.
  • Передача по шине: 2,32 МБ на кадр в обе стороны, плюс накладные расходы протокола и задержки на инициацию транзакций [48].
  • Переключение контекстов: сборка на пять контекстов проходит через чип пятью фазами, и на каждой границе есть служебная работа. Ее величина нам неизвестна — это гипотеза H2.
  • Синхронный режим работы: при глубине очереди в один кадр ускоритель простаивает, пока хост готовит следующий тензор, а хост ждет, пока ускоритель досчитает текущий. Классическая потеря на конвейеризации, лечится асинхронной подачей.
  • Условия замера: неизвестно, что именно входило в измеряемый интервал и в каком тепловом состоянии находился узел (глава 4).

Отчет компилятора добавляет к этому еще один факт, важный для интуиции. Средняя загрузка умножителей по контекстам в нашей сборке — около 0,11 от пиковой, при том что «активная» загрузка внутри работающих блоков держится на уровне 0,75. Это означает, что паспортные тринадцать триллионов операций в секунду для этой сети недостижимы принципиально: сеть с малым числом каналов на ранних слоях не заполняет массив целиком. То же самое на других архитектурах ускорителей описано в разборах матричных блоков: пиковая производительность достигается только на задачах с высокой операционной интенсивностью, а детекторы малых объектов к ним не относятся [23, 54].

Отдельно про межконтекстный трафик. Отчет дает 2 944 800 байт на кадр между контекстами при нулевом числе портов внешней памяти. То есть эти данные остаются внутри чипа и шину не занимают — важное уточнение, потому что интуитивно кажется наоборот. Наружу едут только граничные тензоры, и именно они входят в расчет потолка по шине в главе 9.

Наконец, про несколько потоков на одном ускорителе. Среда исполнения производителя умеет обслуживать несколько моделей и несколько процессов на одном устройстве, распределяя время планировщиком с круговой дисциплиной и настраиваемыми приоритетами и размерами пакета [46]. Это удобно и это же означает, что при N потоках устройство остается единственным сервером: заявки выстраиваются в очередь, а не выполняются параллельно. Все следствия этого разбираются в двух следующих главах.

глава 13

Суперпозиция потоков: восемь ровных источников дают рваную нагрузку

Теорема Пальма — Хинчина объясняет, почему многопоток ломается раньше, чем считает арифметика

Одна камера отдает кадры равномерно: интервал между ними почти постоянен. Такой поток для очереди — самый удобный из возможных: при детерминированном обслуживании очередь не растет вообще, пока загрузка не достигнет единицы. Именно поэтому замер на одной камере выглядит так хорошо и так плохо предсказывает поведение на восьми.

Когда потоков много и их фазы независимы, суммарный поток заявок к общему ускорителю перестает быть равномерным. Классический результат теории потоков — теорема Пальма — Хинчина: суперпозиция большого числа независимых редких потоков сходится к пуассоновскому [4, 5]. Пуассоновский поток — это поток с пачками: интервалы распределены экспоненциально, коэффициент вариации равен единице, и заявки регулярно приходят группами.

ОДИН ИСТОЧНИК — РОВНЫЙ ШАГИНТЕРВАЛЫ ОДИНАКОВЫ, ОЧЕРЕДЬ НЕ РАСТЕТ ДАЖЕ ПРИ ЗАГРУЗКЕ 0,9ВОСЕМЬ ИСТОЧНИКОВ С НЕЗАВИСИМЫМИ ФАЗАМИ — ПАЧКИТА ЖЕ СРЕДНЯЯ ЗАГРУЗКА, НО ЗАЯВКИ ПРИХОДЯТ ГРУППАМИ: ОЧЕРЕДЬ И ЗАДЕРЖКА РАСТУТТЕОРЕМА ПАЛЬМА — ХИНЧИНА: СУММА МНОГИХ РЕДКИХ НЕЗАВИСИМЫХ ПОТОКОВ СХОДИТСЯ К ПУАССОНОВСКОМУПОЭТОМУ ВОСЕМЬ КАМЕР ПО 12 ДЕТЕКЦИЙ — ЭТО НЕ ТО ЖЕ САМОЕ, ЧТО ОДНА КАМЕРА НА 96
Рис. 4. Сверху — заявки от одного источника: ровный шаг, очередь не растет. Снизу — сумма восьми таких же источников с независимыми фазами: та же средняя интенсивность, но заявки идут группами. Для очереди это принципиально разные нагрузки, хотя среднее у них одинаковое.

Количественно переход описывается приближением для коэффициента вариации объединенного потока: он линейно интерполирует между вариацией отдельного источника и единицей по мере роста числа источников [7, 8].

c²_a(N) ≈ (1/N) · c²_1 + (1 − 1/N)

где c²_1 — квадрат коэффициента вариации интервалов одного источника (для ровной камеры близок к нулю); N — число источников; c²_a(N) — то же для объединенного потока

(7)
При N = 1 получаем ровный поток, при N = 8 — уже 0,88, то есть почти пуассоновский. В следующей главе видно, во что это обходится: в формуле Кингмана коэффициент вариации входит прямо в множитель задержки. Проще говоря, восемь камер по 12 детекций в секунду создают на ускорителе более тяжелую нагрузку, чем одна камера с 96 детекциями, при абсолютно одинаковой средней загрузке.
глава 14

Очередь: где именно начинают сыпаться кадры

Первой ломается задержка, а не пропускная способность, и происходит это задолго до перегруза

Вопрос «в какой момент начинают теряться кадры» имеет неприятный ответ: обычно заметно раньше, чем спрос сравняется с пропускной способностью, и не в виде потерь, а в виде задержки. Универсальное приближение для системы общего вида — формула Кингмана [3].

W_q ≈ ( ρ / (1 − ρ) ) · ( (c²_a + c²_s) / 2 ) · S

где W_q — среднее ожидание в очереди; ρ — загрузка сервера; c²_a, c²_s — квадраты коэффициентов вариации интервалов прихода и времени обслуживания; S — среднее время обслуживания

(8)
Формула раскладывает задержку на три независимых множителя: загрузка, дисперсия и среднее время обслуживания. Управлять можно всеми тремя, и дисперсия обходится ровно так же дорого, как загрузка. Система с загрузкой 0,8 и рваным входом ведет себя хуже, чем система с загрузкой 0,9 и ровным.
загрузка ρc²a+c²s = 0,2= 1,0= 2,0= 4,0
0,51,1 мс5,5 мс11,1 мс22,2 мс
0,72,6 мс12,9 мс25,9 мс51,8 мс
0,84,4 мс22,2 мс44,4 мс88,8 мс
0,910,0 мс50,0 мс99,9 мс199,8 мс
0,9521,1 мс105,4 мс210,9 мс421,8 мс
0,9854,4 мс271,9 мс543,9 мс1 087,8 мс
Расчет по формуле (8) при среднем времени обслуживания 11,1 мс — это наш случай при инференсе 90 кадров в секунду. Читать таблицу надо по строкам: переход загрузки с 0,8 на 0,95 при неизменной дисперсии удорожает ожидание в пять раз. Это и есть причина, по которой проектная точка узла лежит около 0,6–0,7, а не «пока не начнет падать».

Для частного случая с детерминированным обслуживанием и пуассоновским входом есть точный результат Полячека — Хинчина, и он же дает нижнюю границу того, что вообще достижимо при ровном сервере [4, 6].

L_q = ρ² / ( 2 · (1 − ρ) )

где L_q — среднее число заявок, ожидающих в очереди, для системы M/D/1

(9)
Числа для наглядности: при ρ = 0,5 в очереди в среднем четверть кадра, при 0,8 — полтора, при 0,9 — четыре, при 0,95 — девять. Отсюда же требование к глубине буфера: буфер меньше среднего значения очереди гарантирует потери, а буфер сильно больше — гарантирует устаревшие кадры.

Собственно потери возникают из-за конечности буфера. Здесь важно различать два режима. Пока спрос ниже пропускной способности, потери определяются дисперсией: кадры теряются в редких пачках, доля их мала и растет плавно. Как только спрос превышает пропускную способность, потери становятся структурными и равны прямой разнице между спросом и возможностями — никакой буфер здесь уже не помогает, он только добавляет задержку.

число потоковзагрузкавыдано на потокпотериp99 задержки
10,1412,5 дет/с0 %11 мс
20,2812,5 дет/с0 %21 мс
40,5612,5 дет/с0 %30 мс
60,8312,5 дет/с0 %40 мс
70,9712,5 дет/с0 %49 мс
81,0011,3 дет/с9,9 %350 мс
101,009,0 дет/с28,0 %439 мс
121,007,5 дет/с40,0 %526 мс
Расчет по дискретно-событийной модели: N независимых источников 25 к/с с децимацией вдвое, общая очередь к ускорителю, время инференса 11,1 мс, буфер 4 кадра на поток, джиттер источника 12 % периода. Обрыв между семью и восемью потоками резкий: задержка растет постепенно и предсказуемо, а потери появляются сразу большими. Это расчет, а не замер, и его задача — быть опровергнутым на стенде.

Отдельно о дисперсии времени обслуживания. Сам по себе инференс на ускорителе — операция с очень стабильным временем, и это большая удача. Но реальное обслуживание включает подготовку тензора и разбор выходов на процессоре, а они конкурируют с декодированием. При загрузке 0,97 рост коэффициента вариации обслуживания с нуля до 0,35 поднимает расчетную p99 с 49 до 121 мс — то есть дисперсия, наведенная процессорной частью, портит показатель сильнее, чем сам ускоритель.

глава 15

Масштабирование по ядрам: Амдал, Густафсон и универсальный закон

У кривой производительности есть максимум, после которого добавление потоков вредит

Процессорная часть конвейера параллелится по четырем ядрам, но не линейно. Классика вопроса — закон Амдала: доля последовательной работы ограничивает ускорение сверху независимо от числа исполнителей [9]. Возражение Густафсона тоже уместно: при росте объема задачи доля последовательной части падает, и практический выигрыш выше пессимистичной оценки [10]. Для нашей задачи обе модели неполны, потому что не учитывают главного — издержек на согласование.

C(N) = N / ( 1 + α·(N − 1) + β·N·(N − 1) )

где C(N) — пропускная способность на N рабочих в единицах производительности одного; α — доля работы, требующей общего ресурса (конкуренция); β — издержки согласованности между рабочими

(10)
Универсальный закон масштабируемости Ганта [11, 12]. При β = 0 он вырождается в закон Амдала. Ключевое отличие: при β > 0 у кривой есть максимум, после которого суммарная производительность падает. Это не теоретический курьез, а обычное поведение многопоточных конвейеров, где потоки делят один блокируемый ресурс — например, распределитель памяти или очередь к устройству.
N* = sqrt( (1 − α) / β )

где N* — число рабочих, при котором пропускная способность максимальна

(11)
Точка, дороже которой стоит только ее незнание. Если у конвейера α = 0,08 и β = 0,008, максимум приходится примерно на одиннадцать рабочих потоков, а на шестнадцати система работает хуже, чем на восьми. Инженер, добавляющий потоки «чтобы загрузить все ядра», регулярно оказывается справа от этого максимума.
сценарийN=1N=2N=4N=8N=12N=16максимум
идеальное масштабирование1,002,004,008,0012,016,0нет
конкуренция α=0,081,001,853,235,136,387,27нет
α=0,08, β=0,0081,001,822,993,984,093,88N ≈ 10,7
тяжелый случай α=0,20, β=0,021,001,612,172,272,051,82N ≈ 6,3
Расчет по формуле (10). Третья строка — типичное поведение конвейера с общей очередью и разделяемой памятью. Обратите внимание: разница между четырьмя и восемью потоками здесь всего треть, а между восемью и шестнадцатью — отрицательная. Коэффициенты α и β снимаются из замера на 1, 2, 4 и 8 потоках методом наименьших квадратов, и это одна из главных причин мерить именно этот ряд.
глава 16

Тепловой контур: пятый ресурс, который отдает счет через двенадцать минут

Замер короче трех постоянных времени измеряет теплоемкость корпуса, а не производительность узла

Кремний греется, корпус мешает теплу уходить, прошивка снижает частоту при достижении порога. На Raspberry Pi 5 пороги названы прямо: с 80 °C ядра начинают прогрессивно замедляться, с 85 °C ограничение становится жестким и распространяется на графику [40]. Ускоритель при этом продолжает работать в своем режиме, но данные ему готовит уже замедленный процессор — и весь конвейер едет вниз.

Тепловое поведение узла описывается одноемкостной моделью — тем же аппаратом, что используется в тепловом моделировании процессоров, только на уровне всего изделия [49, 50]. Мощность создает превышение температуры над средой, пропорциональное тепловому сопротивлению; теплоемкость определяет, за какое время это превышение устанавливается.

ТЕПЛО ИДЕТ ПО ЦЕПОЧКЕ СОПРОТИВЛЕНИЙ, КАЖДОЕ ЗВЕНО ДОБАВЛЯЕТ ГРАДУСЫ И ИНЕРЦИЮкристаллC ≈ единицы Дж/КR1радиаторC ≈ десятки Дж/КR2корпусC ≈ сотни Дж/КR3средабесконечнаяP, ВтУСТАНОВИВШЕЕСЯ ПРЕВЫШЕНИЕ: ΔT = P · (R1 + R2 + R3) — НЕ ЗАВИСИТ ОТ ЕМКОСТЕЙЕМКОСТИ ЗАДАЮТ ТОЛЬКО ВРЕМЯ ВЫХОДА НА НЕГО: τ = R · C, МИНУТЫ, А НЕ СЕКУНДЫЗАМЕР КОРОЧЕ 3τ МЕРЯЕТ ЕМКОСТЬ КОРПУСА, А НЕ ПРОИЗВОДИТЕЛЬНОСТЬ УЗЛАЗАКРЫТЬ КРЫШКУ = УВЕЛИЧИТЬ R3 = СДВИНУТЬ ВСЮ КРИВУЮ ВВЕРХ ПРИ ТОЙ ЖЕ НАГРУЗКЕ
Рис. 5. Тепловой контур узла как цепь сопротивлений: кристалл — радиатор — корпус — среда. Установившееся превышение температуры определяется суммой сопротивлений и не зависит от емкостей; емкости задают только время выхода на режим. Закрытая крышка — это увеличение последнего сопротивления, то есть сдвиг всей кривой вверх при неизменной нагрузке.
T(t) = T_amb + P · R_th · ( 1 − e^(−t/τ) ), τ = R_th · C_th

где T_amb — температура среды; P — рассеиваемая мощность, Вт; R_th — суммарное тепловое сопротивление, °C/Вт; C_th — теплоемкость, Дж/°C; τ — постоянная времени

(12)
Оба параметра снимаются с одной кривой разогрева. Установившееся превышение дает R_th = ΔT/P; время достижения 63 % от него дает τ. Двадцать минут прогона — и модель узла в конкретном корпусе построена. Дальше она отвечает на вопросы вида «что будет в шкафу при +40» без единого дополнительного эксперимента.
P_sust = ( T_limit − T_amb ) / R_th , derate = max( 0, 1 − P_sust / P_demand )

где P_sust — мощность, которую корпус рассеивает бесконечно, не доходя до порога; T_limit — порог троттлинга; P_demand — мощность, которую запрашивает нагрузка; derate — доля производительности, которую придется вернуть

(13)
Это самая недооцененная формула в проектировании edge-узлов. Она говорит, что устойчивая производительность узла определяется не чипом, а корпусом и температурой в месте установки. Один и тот же узел в вентилируемом шкафу и в герметичном боксе на южной стене — это два разных изделия с разной ценой за камеру.
сценарийR_thмощностьустановилось бы напорог 80 °C через
открытый стенд, радиатор, +25 °C4,0 °C/Вт9,5 Вт63 °Cне дойдет
закрытый корпус, без обдува, +25 °C6,5 °C/Вт9,5 Вт87 °C11 мин
закрытый корпус, без обдува, +35 °C6,5 °C/Вт9,5 Вт97 °C5 мин
корпус с обдувом, +25 °C2,2 °C/Вт9,5 Вт46 °Cне дойдет
Расчет по формуле (12) при τ = 300 с. Значения теплового сопротивления взяты как правдоподобные ориентиры для соответствующих конструкций и подлежат замеру — это первая строка протокола части V. Смысл таблицы в другом: две первые строки отличаются только крышкой, и одна из них проходит приемку, а вторая нет.
интерактив · разогрев и троттлинг, формулы (13)–(15)окно 30 минут
установилось бы на
87 °C
первая просадка через
11,1 мин
корпус тянет вечно
8,5 Вт
потеря темпа
11%

Пятиминутный замер попадает в левую часть кривой, где еще ничего не произошло. Смета живет в правой. Разница между ними — последняя колонка: столько производительности узел отдаст обратно, когда корпус прогреется, и ровно на столько же придется уменьшить число камер, если охлаждение не трогать. Поставьте тепловое сопротивление в 8–10 °C на ватт, как у герметичного бокса без обдува, и посмотрите, во что превращается «замерили 90 FPS».

Последнее, о чем стоит сказать в этой главе, — энергия на одну детекцию. Величина полезная тем, что связывает вычислительную и тепловую стороны напрямую: сколько джоулей стоит один вызов детектора, столько же тепла придется отвести.

E_det = P_node / ( N · f_det )

где P_node — потребляемая мощность узла под нагрузкой, Вт; N · f_det — суммарная частота детекций по всем потокам

(14)
Ориентиры для интуиции: узел на 7 Вт при 90 детекциях в секунду тратит около 78 мДж на детекцию, тот же узел на 9 Вт при 200 детекциях — около 45 мДж. Величина падает с ростом загрузки, потому что постоянная составляющая потребления размазывается по большему числу полезных операций. Отсюда неочевидный вывод: недогруженный узел энергетически невыгоден, и восемь камер на одном узле экологичнее, чем по две на четырех, — если восемь помещаются.
Часть IV

Модель бюджета и предсказания

Аппарат из части III собирается в одну формулу с семью параметрами, из которых шесть известны, а один ждет замера. Дальше — численные предсказания для одного, двух, четырех и восьми потоков, разбор рычагов по соотношению «эффект на рубль» и калькулятор, в котором читатель подставляет свои цифры. Все числа этой части — расчет, и каждое сформулировано так, чтобы его можно было опровергнуть на стенде.

глава 17

Четыре потолка в одной формуле

Сколько камер тянет узел — это минимум из четырех независимых ограничений

Каждый ресурс узла разрешает какое-то число камер. Разрешения независимы, считаются по отдельности и выражаются в одних и тех же единицах. Итоговое число камер равно минимальному из них — это прямое следствие закона узкого места (6).

⎧ 1000·u / ( f_det · t_npu ) ускоритель ⎪ B_eff·u / ( f_det · S_bus ) шина N_max = min ⎨ ⎪ 1000·u·C·η(N) / ( f_src·t_dec + f_det·(t_pre + t_post) ) ядра ⎩ P_sust / P_cam тепло

где u — проектный запас загрузки (мы берем 0,7); t_npu — время инференса, мс; S_bus = S_in + S_out — трафик кадра по шине; B_eff — эффективная полоса линии; C — число ядер; η(N) — эффективность масштабирования по формуле (10); t_dec, t_pre, t_post — процессорное время декодирования, подготовки и разбора; P_sust — устойчивая мощность корпуса по формуле (13); P_cam — прирост мощности на одну камеру

(15)
Четыре слагаемых — это ускоритель, шина, ядра и тепло. Множитель u ставится один раз и означает решение проектировать узел с запасом: из главы 14 видно, что при загрузке выше 0,85 задержка растет быстрее, чем линейно, и любая неучтенная мелочь выбрасывает систему за порог.

Параметров в формуле семь, и это хорошая новость. Три берутся из документации (B_eff, C, пороги), два — из отчета компилятора (S_in, S_out), один — из живого замера прошлого года с оговорками главы 4 (t_npu), и ровно один неизвестен совсем — процессорная стоимость стадий t_dec, t_pre, t_post. Именно поэтому протокол части V начинается не с многопоточного прогона, а с раздельного измерения стадий на одном потоке: без этого модель имеет свободный параметр, а с ним — ни одного.

глава 18

Что модель предсказывает для нашего узла

Три камеры при полном FPS, шесть при децимации вдвое, двенадцать при децимации вчетверо

Подставим наши числа. Время инференса 11,1 мс — это обратная величина к верхней границе живого замера (90 к/с). Граничные тензоры 1,23 и 1,09 МБ. Ядер четыре, коэффициенты масштабирования взяты умеренными (α = 0,08, β = 0,008). Источники — 1080p при 25 к/с. Стоимость декодирования принята в 6 мс на кадр для программного H.264 и 1,2 мс для аппаратного H.265; обе цифры — оценки, подлежащие замеру.

сценарийускорительшина Gen2шина Gen3ядратепло
H.264, детекция каждого кадра3,66,913,812,94,8
H.264, детекция каждого второго7,213,827,615,77,0
H.265, детекция каждого кадра3,66,913,826,67,0
H.265, детекция каждого третьего10,820,741,452,117,1
Сколько камер разрешает каждый ресурс по отдельности, расчет по формуле (15) без проектного запаса. Итог по строке — минимум. Главный вывод виден сразу: в трех случаях из четырех первым упирается ускоритель, а не процессор, шина или тепло. Тринадцать триллионов операций в секунду звучат как «камер поместится сколько угодно», а на деле дают три с половиной камеры при полной частоте.

Второй расчет — динамический: что произойдет с задержкой и потерями при разном числе потоков. Здесь работает дискретно-событийная модель из главы 14, в которую заложены независимые фазы источников и джиттер 12 % периода.

потоковзагрузка ускорителявыдано на потокпотериp50p95p99
10,2825,0 дет/с0 %11 мс11 мс11 мс
20,5625,0 дет/с0 %11 мс20 мс22 мс
30,8325,0 дет/с0 %13 мс24 мс29 мс
41,0022,5 дет/с9,9 %164 мс179 мс185 мс
61,0015,0 дет/с40,0 %254 мс268 мс274 мс
81,0011,3 дет/с55,0 %344 мс358 мс363 мс
Предсказание модели для профиля «1080p25, детекция каждого кадра, время инференса 11,1 мс, буфер 4 кадра на поток». Три камеры — рабочая точка, четыре — уже за обрывом. Обратите внимание на характер отказа: не плавная деградация, а скачок. Задержка при этом растет заранее и служит ранним индикатором, потери приходят позже и сразу большими.

Третий расчет — под договорный порог задержки. Он отвечает на вопрос, который заказчик задает вторым: не «сколько камер», а «сколько камер при условии, что событие приходит не позже, чем через столько-то».

порог p99детекция каждого кадракаждого второгокаждого четвертого
60 мс3 потока (75 дет/с)6 потоков (75 дет/с)12 потоков (75 дет/с)
100 мс3 потока (75 дет/с)7 потоков (88 дет/с)14 потоков (88 дет/с)
150 мс3 потока7 потоков14 потоков
250 мс3 потока7 потоков14 потоков
Расчет при коэффициенте вариации обслуживания 0,2. Таблица показывает важное: ослабление требований к задержке почти ничего не дает. Узел ограничен пропускной способностью, а не терпением заказчика, и после насыщения ускорителя послабления по времени отклика не превращаются в дополнительные камеры. Суммарная производительность во всех строках упирается в одни и те же 75–88 детекций в секунду.

И последнее в этой главе — цена прогрева. Возьмем узел, спроектированный на шесть потоков с загрузкой 0,83, и дадим ему двадцатипроцентное замедление процессорной части, соответствующее уходу в мягкий троттлинг.

состояние4 потока6 потоков7 потоков8 потоков
холодный узел, потери0 %0 %0 %10,0 %
холодный узел, p9931 мс41 мс59 мс357 мс
после троттлинга, потери0 %0,1 %14,2 %24,9 %
после троттлинга, p9939 мс292 мс378 мс436 мс
Расчет: те же условия, время обслуживания увеличено на 20 %. Конфигурация на шесть потоков, которая на холодном узле имела двукратный запас по задержке, после прогрева выходит на границу. Это и есть ответ на вопрос, зачем в протоколе двадцать минут прогрева: пятиминутный замер такой конфигурации показал бы отличный результат, а объект получил бы систему, которая ломается к обеду.
глава 19

Рычаги: что дает эффект и сколько стоит

Децимация бьет по всем четырем потолкам сразу и стоит ноль рублей

Все способы увеличить число камер на узле сводятся к шести приемам. Ниже они выстроены по отношению эффекта к стоимости, а не по популярности в презентациях.

децимация
детектор вызывается на каждом k-м кадре, промежутки закрывает трекер. Эффект линейный по k и действует одновременно на ускоритель, шину, ядра (частично) и тепло. Стоимость — ноль рублей и несколько дней на подбор k. Ограничение обсуждается ниже.
смена кодека на камерах
перевод источников на H.265 переносит декодирование с ядер в аппаратный блок [41]. Эффект — только по процессорному потолку, зато большой. Стоимость нулевая, если решается до закупки камер, и высокая, если после.
суб-поток пониженного разрешения
детектору отдается второй поток камеры 1280×720 вместо 4K. Уменьшает и декодирование, и препроцессинг. Ограничение физическое: пикселей на цели должно остаться достаточно, и это проверяется метрикой, а не на глаз.
режим линии PCIe
перевод в Gen 3 удваивает потолок по шине [43, 47]. Стоит ничего, но помогает только тогда, когда шина действительно узкое место; по нашим расчетам это не наш случай, пока не выросло разрешение.
охлаждение
снижение теплового сопротивления возвращает те самые двадцать процентов темпа из главы 18. Стоимость — радиатор и вентилятор, то есть единицы процентов от цены узла; эффект — прямой рост устойчивой производительности.
смена сборки детектора
меньшее разрешение входа или более легкая архитектура уменьшают t_npu. Единственный рычаг, который стоит времени инженера и портит метрики качества, поэтому идет последним, а не первым.
изменениекамер до потолкаотносительно базы
база: H.265, детекция каждого второго, Gen 37,2
детекция каждого кадра3,6−50 %
детекция каждого четвертого14,4+100 %
программный H.264 вместо аппаратного H.2657,20 %
источник 15 к/с вместо 2512,0+67 %
PCIe Gen 2 вместо Gen 37,20 %
Чувствительность потолка к параметрам, расчет по формуле (15). Две строки с нулевым эффектом показательны: пока узкое место — ускоритель, ни кодек, ни режим шины не меняют ничего. Это ровно та ситуация, в которой команда тратит неделю на оптимизацию декодера и получает ноль прироста.

Теперь про ограничение децимации, потому что бесплатных обедов не бывает. Пропуск кадров допустим ровно до тех пор, пока трекер способен связать положения цели между детекциями. Условие формулируется через смещение цели за интервал между вызовами детектора: оно должно оставаться меньше характерного размера цели, иначе ассоциация по перекрытию рамок разваливается [56, 58].

k_max ≈ ( w_px / v_px ) · f_src · γ

где w_px — характерный размер цели в пикселях; v_px — скорость цели в пикселях в секунду; f_src — частота источника; γ — коэффициент запаса, на практике 0,3–0,5

(16)
Пример для интуиции: цель шириной 40 пикселей движется со скоростью 200 пикселей в секунду, источник дает 25 к/с, запас 0,4. Получаем k_max = (40/200)·25·0,4 = 2. То есть детектор можно вызывать через кадр, но не через три. Для медленных сцен (проходная, склад) k доходит до пяти и выше, для быстрых (транспорт, малоразмерные летящие цели) падает до единицы — и именно поэтому число камер на узел нельзя назвать в отрыве от задачи.
глава 20

Калькулятор бюджета

Те же формулы, но с ползунками: подставьте свои цифры и посмотрите, что упрется первым

Ниже — та же модель, что и в таблицах выше, только интерактивная. Четыре шкалы показывают загрузку ресурсов, столбиковая развертка — до какого числа камер узел держится, а нижние показатели считаются дискретно-событийной моделью очереди. Значения по умолчанию соответствуют нашему узлу.

интерактив · бюджет узла, формулы (7)–(12)расчет, не замер
декодирование
шина
корпус
ускоритель111%

100 детекций/с × 11,1 мс

ядра31%

декод 6,0 мс/кадр + 3,3 мс на детекцию

шина58%

232 МБ/с из 400

тепло79%

7,1 Вт из 9 Вт устойчивых

узкое место
ускоритель
камер до потолка
3
задержка p99
184 мс
потери кадров
9,8%

Вердикт на текущих ползунках: перегруз. Узел просят отдать 100 детекций в секунду, каждая стоит 11,1 мс на ускорителе и 2,32 МБ трафика по шине. Первым упирается ускоритель — и пока эта шкала не опустится ниже единицы, любые улучшения остальных трех ничего не дадут. Самый дешевый рычаг тут не железо: поднимите k на единицу и посмотрите, что произойдет со всеми четырьмя шкалами сразу.

Три эксперимента, которые стоит проделать прямо в панели. Первый: поставьте восемь камер при детекции каждого кадра и посмотрите, какая шкала уходит за единицу первой. Второй: не трогая число камер, поднимите децимацию до двух и обратите внимание, что вниз пошли все четыре шкалы сразу. Третий: верните децимацию и вместо этого переключите корпус на герметичный — увидите, как тепловая шкала обгоняет остальные и становится узким местом при том же самом железе.

Часть V

Протокол замера: один день на стенде

Методика, матрица эксперимента, точки съема, критерии отказа и код стенда. Протокол написан до того, как снят первый многопоточный замер, — это сознательное решение: методика, придуманная после знакомства с результатами, всегда объясняет ровно эти результаты. Отдельная глава посвящена способам обмануть себя при замере производительности; все перечисленные ошибки мы либо делали, либо видели.

глава 21

Что измеряем и где стоят точки съема

Восемь величин, три метки времени, одна железная договоренность про то, где считать FPS

СТЕНД: ЧТО ПОДАЕМ, ЧТО СНИМАЕМ И ГДЕ СТОЯТ ТОЧКИ ИЗМЕРЕНИЯгенератор потоковN × RTSP, фиксированныйфайл, GOP и битрейтизвестны заранееузел под нагрузкойдекодпрепроцессинференспостобработкакорпус закрыт, крышка на месте, питание штатноепрогрев 20 минут до начала окнателеметрия, 1 Гцтемпература · частоты · биты троттлингазагрузка ядер · ток и напряжениеглубина очередей · счетчики потерьT1 кадр декодированT2 тензор ушел в чипT3 событие готовоСКВОЗНАЯ ЗАДЕРЖКА СЧИТАЕТСЯ ОТ МЕТКИ ИСТОЧНИКА ДО T3, А НЕ ОТ T1FPS СНИМАЕТСЯ НА ВЫХОДЕ КОНВЕЙЕРА: СЧЕТЧИК НА ВХОДЕ МЕРЯЕТ КАМЕРУ, А НЕ УЗЕЛ
Рис. 6. Схема стенда. Слева генератор потоков с заранее известными параметрами, в центре узел в штатном корпусе, справа съем телеметрии раз в секунду. Красные точки — метки времени внутри конвейера. Сквозная задержка считается от метки источника до T3, а не от T1: разница между этими двумя определениями на загруженном узле достигает сотен миллисекунд.
goodput
число кадров, дошедших до логики решения, деленное на длительность окна. Снимается на выходе конвейера, отдельно по каждому потоку. Это и есть тот FPS, который идет в договор.
потери
число кадров, отброшенных на любой стадии, к числу пришедших. Считается счетчиками в каждой очереди отдельно: важно знать не только сколько, но и где.
задержка
распределение времени от метки источника до готового события. Фиксируются p50, p95, p99 и максимум. Среднее не фиксируется вовсе — оно скрывает ровно то, ради чего замер делается.
разложение по стадиям
время декодирования, препроцессинга, инференса и постобработки по отдельности. Это параметры D_r формулы (6), без них модель не замкнута.
температура и частоты
температура кристалла, текущая частота ядер, слово состояния троттлинга. Снимаются раз в секунду весь прогон, включая прогрев.
мощность
потребление узла под нагрузкой. Снимается по данным контроллера питания и сверяется с внешним измерителем хотя бы один раз — данные PMIC годятся для динамики, но не для абсолютной точности.
глубины очередей
мгновенная и максимальная длина каждой очереди. Показывает, где копится задержка, до того как начнутся потери.
загрузка ядер
по каждому ядру отдельно, вместе с временем ожидания ввода-вывода. Суммарная загрузка на четырех ядрах маскирует ситуацию «одно ядро в потолке, три простаивают», а она встречается чаще всего.
глава 22

Матрица эксперимента и статистика окна

Двадцать минут прогрева, двадцать минут окна, три повтора — и никакой середины

Матрица строится вокруг ряда 1, 2, 4, 8 потоков — из главы 15 понятно, зачем именно он: две точки задают конкуренцию, третья — издержки согласованности, четвертая проверяет модель. К ряду добавляются три бинарных фактора и один трехуровневый.

факторуровнизачем
число потоков1, 2, 4, 8подгонка и проверка модели масштабирования
кодек источникаH.264, H.265оценка цены программного декодирования, глава 7
децимацияk = 1, 2, 4проверка главного рычага, глава 19
корпусоткрытый, закрытыйоценка теплового сопротивления и потери темпа, глава 16
режим линииGen 2, Gen 3проверка потолка по шине, глава 9
Полный перебор дал бы 96 прогонов по 40 минут — это неделя. Поэтому матрица дробная: полный ряд по потокам снимается на базовой конфигурации, а остальные факторы проверяются по одному изменению за раз относительно базы. Такой план ловит главные эффекты и не ловит взаимодействия — про это надо помнить и написать в отчете.

Длительность окна определяется двумя требованиями: тепловым и статистическим. Тепловое — прогон должен идти дольше трех постоянных времени, иначе измеряется не производительность, а теплоемкость корпуса (глава 16). При τ порядка пяти минут это минимум двадцать минут прогрева до начала окна.

SE(p) = sqrt( p·(1 − p) / n )

где p — оцениваемая квантиль (для p99 это 0,99); n — число наблюдений в окне; SE — стандартная ошибка доли

(17)
Статистическое требование: чтобы говорить о p99, нужны десятки тысяч кадров. При 25 к/с окно в 7 минут дает 10 000 наблюдений и стандартную ошибку около 0,1 процентного пункта; окно в 40 минут дает 60 000 и 0,04 п.п. Окно в одну минуту дает 1 500 наблюдений, и разговор о девяносто девятой квантили на таком материале лишен смысла [19, 20].
  • Холодный старт, узел в штатном корпусе, крышка закрыта, температура среды записана.
  • Прогрев 20 минут под целевой нагрузкой; телеметрия пишется с первой секунды, она же дает кривую для оценки R_th и τ.
  • Окно измерения 20 минут; в это время никаких действий по SSH, никаких сборок, никаких сторонних процессов.
  • Три повтора каждой конфигурации, между повторами узел остывает до температуры среды плюс пять градусов.
  • Контрольный прогон базовой конфигурации в конце дня: если он разошелся с утренним больше чем на 5 %, день признается недостоверным и повторяется.
глава 23

Код стенда

Генератор потоков, съем телеметрии, замер конвейера и обработка — четыре листинга

Стенд собирается из общедоступных инструментов. Источники потоков поднимаются на отдельной машине, чтобы не тратить ядра измеряемого узла на генерацию; это принципиально, потому что генерация восьми потоков H.264 стоит примерно столько же, сколько их прием.

bash · генератор N потоков на отдельной машине
#!/usr/bin/env bash
# Поднимаем N независимых RTSP-источников из одного клипа.
# Клип берем реальный, со сценой заказчика: синтетические градиенты
# сжимаются в разы лучше и занижают цену декодирования.
set -euo pipefail

N=${1:-8}                 # число потоков
CODEC=${2:-h264}          # h264 | hevc
CLIP=${3:-scene_1080p25.mp4}
GOP=50                    # опорный кадр раз в две секунды при 25 к/с
BITRATE=4M

# mediamtx слушает 8554 и раздает то, что мы в него публикуем
mediamtx &
sleep 2

for i in $(seq 1 "$N"); do
  # -re держит реальное время, -stream_loop -1 крутит клип бесконечно
  ffmpeg -hide_banner -loglevel error \
    -re -stream_loop -1 -i "$CLIP" \
    -c:v "$( [ "$CODEC" = hevc ] && echo libx265 || echo libx264 )" \
    -preset veryfast -tune zerolatency \
    -b:v "$BITRATE" -g "$GOP" -keyint_min "$GOP" -sc_threshold 0 \
    -an -f rtsp "rtsp://0.0.0.0:8554/cam$i" &
  sleep 0.37   # разводим фазы источников: см. главу 13
done
wait
Три детали, которые определяют качество замера. Клип должен быть с реальной сценой: на синтетике декодирование дешевле в разы. Структура группы кадров фиксируется явно — иначе кодировщик выберет ее сам и прогоны станут несравнимыми. Задержка между запусками разводит фазы источников: при одновременном старте все опорные кадры приходят синхронно, и это не тот режим, который бывает на объекте.
bash · телеметрия узла, 1 Гц
#!/usr/bin/env bash
# Пишем состояние узла раз в секунду весь прогон, включая прогрев.
# Формат — CSV, потому что его читают и глазами, и скриптом.
set -euo pipefail
OUT=${1:-telemetry.csv}

echo "ts,temp_c,arm_hz,throttled,cpu_busy,mem_used_mb" > "$OUT"
while true; do
  TS=$(date +%s.%N)
  TEMP=$(vcgencmd measure_temp | tr -dc '0-9.')
  ARM=$(vcgencmd measure_clock arm | cut -d= -f2)
  # биты 0-3 — текущее состояние, 16-19 — было с момента загрузки
  THR=$(vcgencmd get_throttled | cut -d= -f2)
  CPU=$(awk '/^cpu /{u=$2+$4; t=$2+$4+$5; if (t>0) printf "%.3f", u/t}' /proc/stat)
  MEM=$(awk '/MemAvailable/{printf "%.0f", ($2)/1024}' /proc/meminfo)
  echo "$TS,$TEMP,$ARM,$THR,$CPU,$MEM" >> "$OUT"
  sleep 1
done
Слово состояния троттлинга разбирается по битам: младшие четыре — что происходит прямо сейчас, старшие — что случалось с момента загрузки [40]. Прогон, в котором хоть раз поднялся бит теплового ограничения, помечается в отчете отдельно: его нельзя сравнивать с прогонами, где этого не было.
python · конвейер с точками съема
"""Замер сквозного конвейера: N потоков, общий ускоритель, честные метки времени.

Каждая стадия таймируется отдельно, каждая очередь имеет предел и счетчик потерь.
Результат — построчный CSV, по которому потом считаются квантили и разложение.
"""
import csv, queue, threading, time
from dataclasses import dataclass, field

QUEUE_DEPTH = 4          # кадров на поток; см. главу 14

@dataclass
class Counters:
    arrived: int = 0
    dropped_decode: int = 0
    dropped_infer: int = 0
    done: int = 0
    stage_ms: dict = field(default_factory=lambda: {"dec": [], "pre": [], "npu": [], "post": []})

def stream_worker(src, infer_q, counters, stop):
    """Один поток: приемка, декодирование, препроцессинг. Ядра тратятся здесь."""
    for frame in src:                     # источник отдает кадр с меткой t_src
        if stop.is_set():
            return
        counters.arrived += 1
        t0 = time.perf_counter()
        img = decode(frame)               # аппаратный блок или ядра — см. главу 7
        t1 = time.perf_counter()
        tensor = preprocess(img)          # масштаб, letterbox, укладка
        t2 = time.perf_counter()
        counters.stage_ms["dec"].append((t1 - t0) * 1e3)
        counters.stage_ms["pre"].append((t2 - t1) * 1e3)
        try:
            infer_q.put_nowait((frame.t_src, frame.stream_id, tensor))
        except queue.Full:
            counters.dropped_infer += 1   # очередь к ускорителю переполнена

def infer_worker(infer_q, counters, stop):
    """Единственный обслуживающий прибор: один ускоритель на все потоки."""
    while not stop.is_set():
        try:
            t_src, sid, tensor = infer_q.get(timeout=0.5)
        except queue.Empty:
            continue
        t2 = time.perf_counter()
        raw = infer(tensor)               # синхронный вызов среды исполнения
        t3 = time.perf_counter()
        events = postprocess(raw, sid)    # разбор выходов, трекер, правила
        t4 = time.perf_counter()
        counters.stage_ms["npu"].append((t3 - t2) * 1e3)
        counters.stage_ms["post"].append((t4 - t3) * 1e3)
        counters.done += 1
        writer.writerow([sid, t_src, t4, (t4 - t_src) * 1e3, len(events)])

# Запуск: по потоку на камеру плюс один обслуживающий поток на ускоритель.
# Второй обслуживающий поток тут не нужен и вреден: устройство одно, а лишний
# поток добавит только конкуренцию за очередь — это тот самый коэффициент beta
# из формулы (10).
Структура намеренно простая: по потоку на камеру, один поток на ускоритель, очереди с явной глубиной и счетчиками. Все три метки времени идут по одним часам (perf_counter), а сквозная задержка считается от метки источника. Кадр, потерянный в очереди, попадает в счетчик именно той очереди, где он был потерян.
python · обработка результатов и подгонка модели
"""Из сырых CSV — в параметры модели: alpha, beta, R_th, tau и таблица отчета."""
import numpy as np, pandas as pd

def quantiles(df):
    lat = df["latency_ms"].to_numpy()
    return dict(n=len(lat), p50=np.percentile(lat, 50),
                p95=np.percentile(lat, 95), p99=np.percentile(lat, 99),
                pmax=lat.max())

def fit_usl(n_workers, throughput):
    """USL (10) в линейной форме: (N/C - 1)/(N-1) = alpha + beta*N."""
    n = np.asarray(n_workers, float)
    c = np.asarray(throughput, float) / throughput[0]
    mask = n > 1
    y = (n[mask] / c[mask] - 1) / (n[mask] - 1)
    beta, alpha = np.polyfit(n[mask], y, 1)
    return alpha, beta, np.sqrt((1 - alpha) / beta) if beta > 0 else np.inf

def fit_thermal(t_s, temp_c, power_w, t_amb):
    """R_th и tau по кривой разогрева: dT = P*R*(1-exp(-t/tau))."""
    dt = temp_c - t_amb
    r_th = dt[-1] / power_w                       # установившееся превышение
    target = 0.632 * dt[-1]                       # уровень одной постоянной времени
    tau = t_s[np.argmax(dt >= target)]
    return r_th, tau

def verdict(row, p99_limit_ms, loss_limit=0.01):
    """Критерий отказа из главы 14: нарушен любой из двух — точка не засчитана."""
    return "ok" if row.p99 <= p99_limit_ms and row.loss <= loss_limit else "fail"
Подгонка USL сделана в линейной форме: так видно, ложатся ли точки на прямую, и сразу понятно, если модель не описывает данные. Оценка теплового сопротивления и постоянной времени берется с той же кривой разогрева, которая писалась во время прогрева, — отдельный эксперимент для этого не нужен.
глава 24

Двенадцать способов обмануть себя при замере

Каждый пункт списка встречается в реальных отчетах, половину мы делали сами

  • Мерить холодным. Пять минут прогона попадают в левую часть тепловой кривой, где еще ничего не произошло. Смета живет в правой части (глава 16).
  • Считать FPS на входе. Счетчик до очередей меряет камеру. Узел при этом может выбрасывать половину кадров, и цифра не изменится.
  • Показывать среднюю задержку. Среднее прячет хвост, а событие опаздывает именно в хвосте [16].
  • Мерить одну камеру и умножать на N. Из главы 13 следует, что суперпозиция потоков ведет себя хуже, чем масштабированный одиночный поток при той же средней нагрузке.
  • Гонять синтетический клип. Градиенты и статичная картинка сжимаются в разы лучше реальной сцены, и декодирование выходит дешевле, чем будет на объекте.
  • Забыть про структуру группы кадров. Разные прогоны с автоматическим выбором опорных кадров несравнимы между собой.
  • Держать открытый корпус. Крышка меняет тепловое сопротивление, а с ним и устойчивую производительность — это разные изделия (глава 16).
  • Работать по SSH во время окна. Компиляция, копирование или даже активная сессия занимают ядро, которого не хватит конвейеру.
  • Не фиксировать режим линии PCIe. Половина потолка по шине зависит от одной строки конфигурации [43].
  • Считать успехом отсутствие потерь. Нулевые потери при p99 в полторы секунды означают, что буфер слишком большой, а система уже неработоспособна [25].
  • Сравнивать прогоны разной длины. Квантиль по тысяче кадров и по шестидесяти тысячам — величины разной надежности (17).
  • Публиковать один прогон. Без повторов и без контрольной точки в конце дня результат неотличим от дрейфа стенда [18, 20].

Отдельно про то, чего протокол сознательно не делает. Он не измеряет качество детекции: precision, recall и метрики трекинга [60, 61] снимаются на других данных и другой методикой, и смешивать эти два эксперимента нельзя. Он не сравнивает платформы между собой — это отдельная работа с отдельным бюджетом. И он не претендует на воспроизводимость чужими руками в чужом корпусе: тепловая часть результата привязана к конкретной механике, и это прямо сказано в границах.

Часть VI

Из кадров в секунду — в смету

Число камер на узел само по себе никого не интересует. Интересует стоимость одной камеро-точки, момент, когда дешевле поставить второй узел, чем более мощный, и то, как записать обязательство в договор, чтобы через год его можно было проверить. Часть переводит модель в эти три величины и разбирает четыре топологии для случая, когда камер больше, чем тянет один узел.

глава 25

Стоимость камеро-точки

Единица измерения проекта — не узел и не камера, а рубль на камеру в год

Смета видеоаналитики складывается из вещей, которые растут по-разному. Часть пропорциональна числу камер (сама камера, монтаж, кабель), часть — числу узлов (вычислитель, ускоритель, корпус, питание, место в шкафу), часть постоянна (сервер событий, интеграция, обучение персонала). Число камер на узел определяет, как средняя часть размазывается по первой.

C_point = C_cam + ( C_node + C_infra ) / N_cam + C_fixed / N_total

где C_point — стоимость одной камеро-точки; C_cam — все, что относится к самой камере; C_node — узел с ускорителем, корпусом и питанием; C_infra — монтаж узла и место в шкафу; N_cam — камер на узел; N_total — всего камер в проекте

(18)
Из формулы видно, почему вопрос «сколько камер тянет узел» стоит первым. Переход с трех камер на узел на шесть уменьшает вторую составляющую вдвое; на объекте из тридцати камер это разница между десятью узлами и пятью, то есть пять корпусов, пять источников питания, пять монтажей и пять точек отказа.

Отсюда же следует, что децимация — это не техническая деталь, а коммерческий инструмент. Решение вызывать детектор через кадр вместо каждого кадра удваивает N_cam и убирает половину узлов из сметы. Оно должно приниматься совместно с заказчиком и фиксироваться в техническом задании — потому что это его деньги и его риск, а не наша внутренняя оптимизация.

решениечто меняет в моделичто меняет в смете
детекция через кадрf_det вдвое нижевдвое меньше узлов
камеры с H.265t_dec почти обнуляетсяснимает процессорный потолок, если он был узким
суб-поток 720p для детектораt_dec и t_pre нижето же плюс запас по шине
активное охлаждение узлаR_th ниже, derate = 0возвращает пятую часть темпа, стоит проценты от узла
источники 15 к/с вместо 25f_src нижеплюс две трети камер на узел
Пять решений, каждое из которых принимается на этапе проектирования и стоит дешевле, чем один дополнительный узел. Ни одно из них не требует замены ускорителя.

Второй вопрос экономики — запас. Проектировать узел в потолок нельзя: из главы 14 видно, что при загрузке выше 0,85 задержка растет быстрее линейного, а из главы 18 — что прогрев съедает пятую часть темпа. Разумная проектная точка — 0,7 по самому загруженному ресурсу в установившемся тепловом режиме.

N_проект = floor( u · N_max ), u = 0,7

где N_max — потолок по формуле (15) в установившемся тепловом режиме; u — проектный запас

(19)
Тридцать процентов запаса выглядят расточительством ровно до первого объекта, где заказчик добавил камеру, сменил разрешение или переставил ее на солнечную сторону. Стоимость запаса известна заранее и мала; стоимость выезда на объект с переделкой — нет и велика.
глава 26

Когда камер больше, чем тянет узел

Четыре топологии, у каждой своя цена ошибки

Ответ «поставим второй узел» верен чаще, чем кажется, но не всегда. Ниже — четыре варианта с честным перечислением того, что каждый ломает.

больше узлов
линейное масштабирование, отказ одного узла уносит только свои камеры, монтаж простой. Растет число точек обслуживания и суммарное потребление: постоянная составляющая мощности платится за каждый узел, и энергия на детекцию (14) ухудшается.
ускоритель мощнее
вдвое более производительный модуль в том же форм-факторе снимает потолок ускорителя, но упирает систему в следующий по очереди — обычно в процессорный. Прирост числа камер получается меньше, чем прирост TOPS, и это надо считать заранее по формуле (15), а не после закупки.
каскад детекторов
дешевый первичный отбор (движение, фон, легкая сеть) отсеивает пустые кадры, тяжелый детектор вызывается на кандидатах. На типичных объектах доля непустых кадров невелика, и выигрыш кратный. Ломает предсказуемость: время обработки становится зависимым от сцены, и в договоре появляется условие на среднюю активность.
агрегация на сервере
узлы отдают наверх не события, а кадры или признаки. Снимает ограничение edge-железа, добавляет требование к каналу связи и делает систему зависимой от него. Для объектов с плохой связью — заведомо не вариант, для объектов с оптикой — часто самый дешевый.

Про сравнение платформ надо сказать прямо. На рынке есть модули с большей паспортной производительностью и модули с меньшей, и у каждого производителя есть свои красивые числа. Наших замеров по чужим платформам нет, и приводить их паспортные величины рядом с нашими измеренными было бы подменой: из главы 12 видно, что разрыв между паспортом и живым замером на одном и том же железе достигает трех с половиной раз. Сравнивать имеет смысл только измеренные в одинаковых условиях величины, а это отдельная работа.

Последнее — формулировка обязательства. В договор идет не «система обрабатывает восемь камер», а конструкция из четырех величин: число потоков, частота детекции на поток, порог задержки p99 и допустимая доля потерь, — плюс условия, при которых это верно: разрешение, кодек, температура среды и тип корпуса. Такое обязательство проверяется приемочным прогоном по протоколу части V и защищает обе стороны: заказчик знает, что покупает, а подрядчик знает, за что отвечает.

SLA = { N потоков ; f_det на поток ; p99 ≤ L мс ; потери ≤ 1 % } при { разрешение, кодек, T_amb, корпус }

где L — договорный порог задержки события

(20)
Четыре числа слева и четыре условия справа. Убрать любое из условий — значит подписаться под тем, что система работает одинаково в лаборатории и в шкафу на южной стене при +40, а это неправда для любого edge-железа.
Часть VII

Границы, гипотезы и план работ

Где модель перестает работать, какие четыре утверждения мы проверяем на стенде, по каким критериям каждое из них будет закрыто и что именно происходит в день замера. Гипотезы сформулированы до эксперимента и с назначенными порогами — иначе любой результат объясняется задним числом, и работа превращается в пересказ того, что и так получилось.

глава 27

Границы применимости

Пять мест, где модель врет, и одно, где она принципиально бессильна

  • Один ускоритель. Вся часть III построена на том, что обслуживающий прибор один. Для узла с двумя ускорителями меняется структура очереди, и формулы (8), (9) надо переписывать под многоканальную систему [8].
  • Постоянная стоимость кадра. Модель считает время инференса неизменным. Для каскадных схем и сетей с ранним выходом это неверно: время начинает зависеть от сцены, и вместо константы нужно распределение.
  • Отсутствие конкуренции за память. При росте числа потоков конкуренция за полосу памяти растет нелинейно, и коэффициент β формулы (10) перестает быть константой. Ряд 1, 2, 4, 8 это поймает, а экстраполяция на 32 потока — нет.
  • Одноемкостная тепловая модель. Реальный узел имеет как минимум три тепловые массы с разными постоянными времени. Для оценки времени до троттлинга и устойчивой мощности этого хватает, для точного предсказания температуры конкретной точки платы — нет [50].
  • Стационарность нагрузки. Модель описывает установившийся режим. Проходная в час пик, ночная смена и пустой цех — три разные нагрузки, и проектировать надо по худшей, а не по средней.
  • Качество детекции. Ни одна формула в работе ничего не говорит о том, найдет ли детектор цель. Бюджет FPS и метрики качества — независимые оси, и хороший результат по одной ничего не обещает по другой.
глава 28

Четыре гипотезы и день на стенде

Каждая с порогом закрытия, назначенным заранее

H1 · узкое место
На профиле 1080p25 с детекцией каждого кадра первым в потолок упирается ускоритель, а не ядра, шина или тепло. Закрывается положительно, если при N = 4 загрузка ускорителя выше 0,95, а остальные три ресурса ниже 0,8. Закрывается отрицательно, если хоть один другой ресурс достигает потолка раньше, — тогда переписывается глава 18 и меняются рекомендации по железу.
H2 · цена переключения контекстов
Разрыв между оценкой компилятора (315 к/с) и живым замером (80–90 к/с) более чем наполовину объясняется хост-частью и передачей по шине, а не служебной работой на границах контекстов. Закрывается положительно, если чистое время инференса, снятое утилитой производителя, окажется не более чем в 1,6 раза выше суммы времен контекстов. Если разрыв внутри самого ускорителя больше — значит, сборку надо перекомпилировать в меньшее число контекстов, и это отдельная работа с понятной ценой.
H3 · выравнивание фаз
Планировщик, выдающий заявки на ускоритель по собственному таймеру вместо факта прихода кадра, снижает p99 задержки при N = 8 не менее чем на 25 % при неизменной пропускной способности. Основание — глава 13 и формула (7). Закрывается отрицательно, если выигрыш меньше 10 %: тогда суперпозиция потоков на нашем масштабе не является значимым фактором.
H4 · цена крышки
Закрытый корпус без обдува уменьшает устойчивое число камер не менее чем на 20 % относительно открытого стенда при той же температуре среды. Закрывается положительно, если разница в устойчивом goodput между двумя прогонами превышает 20 %, и отрицательно, если она меньше 10 %, — во втором случае тепловая часть модели для нашего конструктива избыточна.

Порядок работ на стенде — от дешевого к дорогому, чтобы дорогое имело смысл. День рассчитан на одного инженера и не требует ничего, кроме собранного узла, второй машины под генератор и клипа с реальной сценой.

времячто делаемчто получаем
09:00–09:40чистое время инференса утилитой производителя, три повторанижняя граница t_npu, проверка H2
09:40–10:20раздельный замер стадий на одном потоке, оба кодекаt_dec, t_pre, t_post — последние неизвестные модели
10:20–12:30ряд 1, 2, 4, 8 потоков на базовой конфигурации, открытый стендgoodput, потери, квантили; подгонка α и β; проверка H1
12:30–13:30перерыв, узел остывает до средыконтрольная точка холодного состояния
13:30–15:00тот же ряд в закрытом корпусеR_th, τ, потеря темпа; проверка H4
15:00–16:00децимация k = 2 и k = 4 при N = 8проверка главного рычага, точка отказа по критерию главы 14
16:00–17:00прогон с выравниванием фаз при N = 8проверка H3
17:00–17:30контрольный повтор утренней базовой точкиоценка дрейфа стенда за день
План дня. Первые два пункта закрывают все свободные параметры модели, поэтому остальные шесть уже проверяют предсказания, а не подбирают коэффициенты. Если утренние измерения разойдутся с ожиданиями настолько, что предсказания потеряют смысл, правильное решение — остановиться и переписать модель, а не отрабатывать план до конца.

Что появится на этой странице после прогона: полная таблица по всем точкам матрицы с датой и условиями, телеметрия, подогнанные параметры модели, сравнение предсказание — факт по каждой строке и вердикт по каждой из четырех гипотез. Расчетные числа частей IV и V останутся на своих местах для сравнения, а не будут заменены задним числом: разница между тем, что мы предсказывали, и тем, что получилось, — самая полезная информация во всей работе, и прятать ее незачем.

приложение А

Глоссарий

Термины, которые в тексте используются без расшифровки.

узел
одноплатный компьютер с ускорителем инференса, который принимает N видеопотоков и отдает события. В этой работе — Raspberry Pi 5 с модулем на Hailo-8L, но модель написана так, чтобы переносилась на любой edge-узел с одним ускорителем.
поток
одна камера, подключенная по RTSP. Слово «поток» тут не про программные потоки исполнения: путаница этих двух смыслов — источник половины разночтений в разговорах о производительности.
sustained FPS
частота, которую узел держит после теплового выхода на режим и на реальной сцене. Отличается от пиковой на десятки процентов, и в смету попадает именно она.
goodput
доля кадров, которые дошли до логики принятия решения. Кадр, декодированный и выброшенный из очереди перед ускорителем, в goodput не входит, хотя ядра за него уже заплатили.
детекционный FPS
частота вызовов детектора, f_det = f_src / k, где k — коэффициент децимации. Главный управляемый параметр бюджета: он входит во все четыре потолка линейно.
децимация
прореживание: детектор вызывается не на каждом кадре, промежутки закрывает трекер. Дешевле любого апгрейда железа и почти всегда первый рычаг, который надо трогать.
загрузка ρ
отношение спроса к пропускной способности ресурса. При ρ → 1 задержка растет как 1/(1−ρ), поэтому проектная точка находится в районе 0,6–0,7, а не 0,95.
контекст
часть скомпилированной сети, которая целиком помещается в память ускорителя. Сеть на пять контекстов проходит через чип за пять фаз с переключением между ними — это влияет и на латентность, и на поведение при нескольких моделях.
граничный тензор
вход и выход сборки, которые физически едут по шине между хостом и ускорителем. Все, что происходит между контекстами внутри чипа, шину не занимает.
троттлинг
снижение тактовой частоты при достижении температурного порога. На Raspberry Pi 5 начинается при 80 °C и ужесточается при 85 °C, ускоритель при этом продолжает работать на своей частоте, но данные к нему готовит уже замедленный процессор.
тепловое сопротивление R_th
сколько градусов превышения над средой дает каждый ватт рассеиваемой мощности. Свойство конструкции, а не чипа: закрыть корпус крышкой значит увеличить R_th и подвинуть всю кривую вверх.
постоянная времени τ
произведение теплового сопротивления на теплоемкость. Определяет, за какое время узел выходит на установившуюся температуру: для корпуса это минуты, поэтому замер короче трех τ измеряет не то, что нужно.
USL
универсальный закон масштабируемости Ганта: модель, в которой рост числа рабочих ограничен конкуренцией за общий ресурс (α) и издержками согласованности (β). При β > 0 у кривой есть максимум, после которого добавление потоков снижает суммарную производительность.
теорема Пальма — Хинчина
сумма большого числа независимых редких потоков событий сходится к пуассоновскому. Практическое следствие: восемь ровных камер создают на общем ускорителе гораздо более рваную нагрузку, чем одна камера с восьмикратной частотой.
формула Кингмана
приближение для средней задержки в очереди общего вида: произведение множителя загрузки ρ/(1−ρ), полусуммы квадратов коэффициентов вариации входа и обслуживания и среднего времени обслуживания. Показывает, что дисперсия стоит столько же, сколько загрузка.
p99
задержка, которую не превышают 99 % кадров. В договоре с заказчиком имеет смысл фиксировать именно ее, а не среднее: среднее прячет как раз те кадры, из-за которых событие приходит поздно.
приложение Б

Литература

Только первоисточники, каждый открывается по DOI или на arXiv. Единственное исключение — материалы производителей железа, они помечены прямо в позиции: независимых замеров по этим системам в открытом доступе нет.

  1. [1]Little J. D. C. A Proof for the Queuing Formula: L = λW. Operations Research, 1961, 9(3), 383–387.
  2. [2]Little J. D. C., Graves S. C. Little's Law. In: Building Intuition. Springer, 2008, 81–100.
  3. [3]Kingman J. F. C. The single server queue in heavy traffic. Mathematical Proceedings of the Cambridge Philosophical Society, 1961, 57(4), 902–904.
  4. [4]Khinchin A. Y. Mathematical Methods in the Theory of Queueing. Griffin, London, 1960 (перевод издания 1955 года).
  5. [5]Palm C. Intensitätsschwankungen im Fernsprechverkehr. Ericsson Technics, 1943, 44, 1–189.
  6. [6]Kleinrock L. Queueing Systems. Volume 1: Theory. Wiley-Interscience, 1975.
  7. [7]Whitt W. The Queueing Network Analyzer. Bell System Technical Journal, 1983, 62(9), 2779–2815.
  8. [8]Whitt W. Approximations for the GI/G/m queue. Production and Operations Management, 1993, 2(2), 114–161.
  9. [9]Amdahl G. M. Validity of the single processor approach to achieving large scale computing capabilities. AFIPS Spring Joint Computer Conference, 1967, 483–485.
  10. [10]Gustafson J. L. Reevaluating Amdahl's law. Communications of the ACM, 1988, 31(5), 532–533.
  11. [11]Gunther N. J. Guerrilla Capacity Planning. Springer, 2007.
  12. [12]Gunther N. J. A general theory of computational scalability based on rational functions. arXiv:0808.1431, 2008.
  13. [13]Denning P. J., Buzen J. P. The Operational Analysis of Queueing Network Models. ACM Computing Surveys, 1978, 10(3), 225–261.
  14. [14]Lazowska E. D., Zahorjan J., Graham G. S., Sevcik K. C. Quantitative System Performance: Computer System Analysis Using Queueing Network Models. Prentice-Hall, 1984.
  15. [15]Jain R. The Art of Computer Systems Performance Analysis. Wiley, 1991.
  16. [16]Dean J., Barroso L. A. The Tail at Scale. Communications of the ACM, 2013, 56(2), 74–80.
  17. [17]Fleming P. J., Wallace J. J. How not to lie with statistics: the correct way to summarize benchmark results. Communications of the ACM, 1986, 29(3), 218–221.
  18. [18]Mytkowicz T., Diwan A., Hauswirth M., Sweeney P. F. Producing wrong data without doing anything obviously wrong! ASPLOS, 2009, 265–276.
  19. [19]Georges A., Buytaert D., Eeckhout L. Statistically rigorous Java performance evaluation. OOPSLA, 2007, 57–76.
  20. [20]Hoefler T., Belli R. Scientific benchmarking of parallel computing systems. SC '15, 2015, статья 73.
  21. [21]Reddi V. J. и др. MLPerf Inference Benchmark. ISCA, 2020, 446–459.
  22. [22]Banbury C. и др. MLPerf Tiny Benchmark. NeurIPS Datasets and Benchmarks, 2021.
  23. [23]Williams S., Waterman A., Patterson D. Roofline: an insightful visual performance model for multicore architectures. Communications of the ACM, 2009, 52(4), 65–76.
  24. [24]Sze V., Chen Y.-H., Yang T.-J., Emer J. S. Efficient Processing of Deep Neural Networks: A Tutorial and Survey. Proceedings of the IEEE, 2017, 105(12), 2295–2329.
  25. [25]Gettys J., Nichols K. Bufferbloat: Dark Buffers in the Internet. Communications of the ACM, 2012, 55(1), 57–65.
  26. [26]Nichols K., Jacobson V. Controlling Queue Delay. ACM Queue, 2012, 10(5).
  27. [27]Cruz R. L. A calculus for network delay, Part I: Network elements in isolation. IEEE Transactions on Information Theory, 1991, 37(1), 114–131.
  28. [28]Le Boudec J.-Y., Thiran P. Network Calculus: A Theory of Deterministic Queuing Systems for the Internet. Springer LNCS 2050, 2001.
  29. [29]Liu C. L., Layland J. W. Scheduling algorithms for multiprogramming in a hard-real-time environment. Journal of the ACM, 1973, 20(1), 46–61.
  30. [30]Sha L., Rajkumar R., Lehoczky J. P. Priority inheritance protocols: an approach to real-time synchronization. IEEE Transactions on Computers, 1990, 39(9), 1175–1185.
  31. [31]Buttazzo G. C. Hard Real-Time Computing Systems: Predictable Scheduling Algorithms and Applications. 3-е издание, Springer, 2011.
  32. [32]Schulzrinne H., Casner S., Frederick R., Jacobson V. RFC 3550: RTP — A Transport Protocol for Real-Time Applications. IETF, 2003.
  33. [33]Schulzrinne H., Rao A., Lanphier R. RFC 2326: Real Time Streaming Protocol (RTSP). IETF, 1998.
  34. [34]Schulzrinne H. и др. RFC 7826: Real-Time Streaming Protocol Version 2.0. IETF, 2016.
  35. [35]Wiegand T., Sullivan G. J., Bjontegaard G., Luthra A. Overview of the H.264/AVC video coding standard. IEEE Transactions on Circuits and Systems for Video Technology, 2003, 13(7), 560–576.
  36. [36]Sullivan G. J., Ohm J.-R., Han W.-J., Wiegand T. Overview of the High Efficiency Video Coding (HEVC) Standard. IEEE TCSVT, 2012, 22(12), 1649–1668.
  37. [37]Ohm J.-R., Sullivan G. J., Schwarz H., Tan T. K., Wiegand T. Comparison of the coding efficiency of video coding standards — including HEVC. IEEE TCSVT, 2012, 22(12), 1669–1684.
  38. [38]ITU-T Recommendation H.264 / ISO-IEC 14496-10: Advanced video coding for generic audiovisual services.
  39. [39]ITU-T Recommendation H.265 / ISO-IEC 23008-2: High efficiency video coding.
  40. [40]Raspberry Pi Ltd. Raspberry Pi hardware documentation, раздел Frequency management and thermal control (пороги 80 и 85 °C). Материал производителя.
  41. [41]Raspberry Pi Ltd. Raspberry Pi 5 product brief: BCM2712, четыре ядра Cortex-A76 2,4 ГГц, VideoCore VII, аппаратный декодер HEVC 4Kp60. Материал производителя.
  42. [42]Raspberry Pi Ltd. AI Kit documentation: модуль на базе Hailo-8L, 13 TOPS, подключение по одной линии PCIe. Материал производителя.
  43. [43]Raspberry Pi Ltd. AI HAT+ documentation: варианты 13 и 26 TOPS, автоматическое переключение линии в режим PCIe Gen 3. Материал производителя.
  44. [44]Hailo Technologies. Hailo-8L AI Accelerator: 13 TOPS, типовое потребление 1,5 Вт, архитектура без внешней DRAM. Материал производителя.
  45. [45]Hailo Technologies. Hailo-8L Datasheet, ревизия 1.9.3, апрель 2026. Материал производителя.
  46. [46]Hailo Technologies. HailoRT User Guide: планировщик сетей, multi-process service, режимы batch и приоритетов. Материал производителя.
  47. [47]PCI-SIG. PCI Express Base Specification, Revision 3.0 (кодирование 128b/130b, 8 ГТ/с на линию).
  48. [48]Neugebauer R. и др. Understanding PCIe performance for end host networking. SIGCOMM, 2018, 327–341.
  49. [49]Skadron K. и др. Temperature-aware microarchitecture. ISCA, 2003, 2–13.
  50. [50]Huang W. и др. HotSpot: A compact thermal modeling methodology for early-stage VLSI design. IEEE TVLSI, 2006, 14(5), 501–513.
  51. [51]Brooks D., Martonosi M. Dynamic thermal management for high-performance microprocessors. HPCA, 2001, 171–182.
  52. [52]Esmaeilzadeh H. и др. Dark silicon and the end of multicore scaling. ISCA, 2011, 365–376.
  53. [53]Horowitz M. Computing's energy problem (and what we can do about it). ISSCC, 2014, 10–14.
  54. [54]Jouppi N. P. и др. In-Datacenter Performance Analysis of a Tensor Processing Unit. ISCA, 2017, 1–12.
  55. [55]Redmon J., Divvala S., Girshick R., Farhadi A. You Only Look Once: Unified, Real-Time Object Detection. CVPR, 2016, 779–788.
  56. [56]Bewley A., Ge Z., Ott L., Ramos F., Upcroft B. Simple Online and Realtime Tracking. ICIP, 2016, 3464–3468.
  57. [57]Wojke N., Bewley A., Paulus D. Simple Online and Realtime Tracking with a Deep Association Metric. ICIP, 2017, 3645–3649.
  58. [58]Zhang Y. и др. ByteTrack: Multi-Object Tracking by Associating Every Detection Box. ECCV, 2022.
  59. [59]Kalman R. E. A New Approach to Linear Filtering and Prediction Problems. Journal of Basic Engineering, 1960, 82(1), 35–45.
  60. [60]Bernardin K., Stiefelhagen R. Evaluating Multiple Object Tracking Performance: The CLEAR MOT Metrics. EURASIP JIVP, 2008, статья 246309.
  61. [61]Luiten J. и др. HOTA: A Higher Order Metric for Evaluating Multi-Object Tracking. International Journal of Computer Vision, 2021, 129, 548–578.
  62. [62]Shannon C. E. Communication in the Presence of Noise. Proceedings of the IRE, 1949, 37(1), 10–21.
  63. [63]Jacob B. и др. Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference. CVPR, 2018, 2704–2713.
  64. [64]Krishnamoorthi R. Quantizing deep convolutional networks for efficient inference: A whitepaper. arXiv:1806.08342, 2018.
  65. [65]Nagel M. и др. A White Paper on Neural Network Quantization. arXiv:2106.08295, 2021.
  66. [66]Chen T. и др. TVM: An Automated End-to-End Optimizing Compiler for Deep Learning. OSDI, 2018, 578–594.
  67. [67]Chetlur S. и др. cuDNN: Efficient Primitives for Deep Learning. arXiv:1410.0759, 2014.
  68. [68]GStreamer Project. GStreamer Application Development Manual: пайплайны, очереди, элементы измерения.
  69. [69]FFmpeg Project. FFmpeg documentation: декодирование, бенчмаркинг, генерация тестовых потоков.
  70. [70]Linux kernel documentation. perf: Linux profiling with performance counters.
  71. [71]Gregg B. Systems Performance: Enterprise and the Cloud. 2-е издание, Addison-Wesley, 2020.
  72. [72]Gregg B. The USE Method: Utilization, Saturation, Errors — методика поиска узкого места в системе.
границы

Собственного многопоточного замера у лаборатории пока нет. Измеренное тут одно: 80–90 кадров в секунду на одной камере на нашем стенде, причем условия того замера записаны не полностью, и в работе это сказано прямо. Все остальные числа — либо выкладки компилятора по нашей сборке, либо расчет по модели, либо материалы производителей железа со ссылкой на источник. Модель построена для узла с одним ускорителем, постоянной стоимостью кадра и стационарной нагрузкой; для каскадных схем, двух ускорителей и пиковых режимов ее надо переписывать. О качестве детекции работа не говорит ничего: бюджет FPS и метрики точности — независимые оси.

журнал

Что происходило по направлению

  1. 13.08.2026

    Направление открыто. Разобран отчет компилятора по сборке YOLO11n 640×640 под Hailo-8L: пять контекстов, 3,18 мс суммарного времени счета, граничные тензоры 1,23 и 1,09 МБ, межконтекстный трафик 2,94 МБ на кадр при нулевом числе портов внешней памяти. Зафиксирован разрыв в 3,5 раза с живым замером и разложен на пять составляющих.

  2. 13.08.2026

    Собрана модель бюджета из четырех потолков и посчитаны предсказания для 1, 2, 4 и 8 потоков дискретно-событийной моделью общей очереди. Главный результат расчета: на профиле 1080p25 с детекцией каждого кадра рабочая точка — три камеры, при децимации вдвое — шесть, узкое место во всех случаях ускоритель. Опубликованы калькулятор бюджета и тепловой стенд.

  3. 13.08.2026

    Написан протокол суточного замера с кодом стенда, матрицей эксперимента, критериями отказа и планом дня по часам. Сформулированы четыре гипотезы с назначенными заранее порогами закрытия. Прогон запланирован; расчетные таблицы после него останутся для сравнения с фактом.

Другие направления

Вся витрина R&D →

Статус этого направления — в работе. Как читать статусы и по каким правилам работает лаборатория — на витрине R&D.

— заявка

Опишите задачу  ответим как инженеры. 

Оставьте имя и Telegram — остальное обсудим. Без брифов на 40 слайдов и звонков по три раза.

Отвечаем за пару часовотвечает инженер, а не отдел продажNDA по запросу

Любой один канал — куда удобнее, туда и ответим

Или сразу написать в Telegram

Без спама и звонков-роботов. Нажимая кнопку, вы соглашаетесь с политикой конфиденциальности и обработкой персональных данных.