Frigate i Coral TPU: ile kamer obsłuży jeden akcelerator

Spis treści
Przed każdą instalacją Frigate pada pytanie, ile kamer udźwignie jeden Coral, a odpowiedzią zawsze jest przedział – bo w tej postaci pytanie jest źle zadane. TPU nie przetwarza kamer. Przetwarza inferencje i ma na to dokładnie tysiąc milisekund na sekundę.
Reszta z tego wynika: ile detekcji na sekundę wytwarza instalacja, ile trwa jedna na wybranym akceleratorze i ile z tej sekundy zostaje, gdy kilka kamer ma jednocześnie coś do roboty. Trzy liczby, jedno mnożenie.

Ile naprawdę kosztuje jedna detekcja
Frigate nie wysyła do detektora każdej klatki. Najpierw tani przebieg na procesorze szuka ruchu i wycina obszary, w których coś się zmieniło; tylko one idą do TPU, każdy jako osobna inferencja. Spokojna scena nie kosztuje więc nic, a scena z dwoma rozdzielonymi obszarami ruchu kosztuje dwie inferencje na klatkę zamiast jednej.
Właśnie ten szczegół zamienia liczbę kamer w zgadywankę. Obciążenie to nie kamery razy liczba klatek, tylko kamery razy liczba klatek razy liczba obszarów ruchu – a ostatni czynnik jest własnością kadru, nie sprzętu. Kamera skierowana na żywopłot na wietrze produkuje obszary cały dzień, kamera na zamkniętą bramę nie produkuje ich godzinami.
Rachunek w jednej linijce
inferencje/s = kamery × klatki detekcji × obszary na klatkę
zajętość = inferencje/s × czas inferencji
zapas = 1000 ms/s − zajętość
8 kamer × 5 kl./s × 1,5 obszaru = 60 inferencji/s
60/s × 8 ms = 480 ms/s → 48 % jednego Corala
Współczynnik 1,5 obszaru na klatkę to sensowna wartość robocza dla mieszanych widoków zewnętrznych; ruchliwa ulica potrzebuje dwóch do trzech, cichy korytarz ledwie jednego. Zmierzenie tej liczby zamiast jej założenia opłaca się, bo jako jedyna w tej linijce nie stoi w żadnej specyfikacji.
Dlaczego średnia to zła liczba
Wymiarowanie pod średnią daje instalację, która przez miesiące chodzi wyśmienicie. Średnia jest niska, bo większość kamer przez większość czasu nic nie widzi, a zbudowany na niej budżet nie ma zapasu na popołudnie, gdy przyjeżdża dostawa, pies jest w ogrodzie, a wiatr się wzmaga – trzy kamery zajęte w tej samej sekundzie, i to w tej najważniejszej.
Użytecznym przypadkiem wymiarującym jest przypadek jednoczesny: wszystkie kamery, które wiarygodnie mogą mieć coś do roboty naraz, zajęte naraz, przy ustawionej liczbie klatek. Jeśli ten przypadek mieści się w jednej sekundzie czasu TPU, instalacja nie ma złych popołudni. Jeśli się nie mieści, błąd jest niewidoczny w dzienniku i oczywisty w brakującym nagraniu.
Co daje który detektor
| Detektor | Czas inferencji | Inferencje/s | Kamery przy 5 kl./s |
|---|---|---|---|
| Coral M.2 / PCIe | ~7 ms | 143 | 19 |
| Coral USB w gnieździe USB 3.0 | ~8 ms | 125 | 16 |
| Coral USB w gnieździe USB 2.0 | ~22 ms | 45 | 6 |
| OpenVINO na iGPU Intela | ~15 ms | 66 | 8 |
| Sam procesor, cztery rdzenie | ~90 ms | 11 | 1 |
Trzeci wiersz to najczęstsza rana zadana sobie samemu: ten sam moduł, ten sam model, ten sam kod, tylko w czarnym gnieździe zamiast niebieskiego – i jedna trzecia prędkości. Ostatni wiersz tłumaczy, dlaczego detektor procesorowy jest raczej dowodem wykonalności niż opcją: jedna kamera to nie instalacja.
Dwa akceleratory mniej więcej podwajają pułap, bo Frigate oddaje pracę temu detektorowi, który akurat jest wolny. Czego nie zmniejszają o połowę, opisuje kolejna część.
Wąskim gardłem zwykle nie jest TPU
Zanim klatka trafi do detektora, trzeba ją zdekodować, a dekodowanie to czysta praca procesora, której żaden akcelerator z tego budżetu nie dotyka. Dekodowanie podstrumienia 1280×720 przy 5 kl./s to drobne. Dekodowanie strumienia głównego 4K przy 20 kl./s kosztuje mniej więcej rdzeń na kamerę – dlatego instalacja z ośmioma kamerami potrafi położyć maszynę, podczas gdy TPU stoi na jedenastu procentach.
Układ, który tego unika, jest ten zwyczajny i wart wypowiedzenia wprost: detekcja idzie z podstrumienia, w rozdzielczości, którą kamera i tak nadaje, przy pięciu klatkach na sekundę. Nagrywanie idzie ze strumienia głównego i jest kopiowane, a nie kodowane od nowa – pełna rozdzielczość ląduje na dysku bez zdekodowania ani jednej klatki. Detektor nigdy nie widzi 4K i nigdy nie musi: człowieka znajduje się z kilkuset pikseli obrysu, a nagranie, które ktoś potem obejrzy, to nietknięty strumień główny.
Po czym poznać nasycenie
Frigate podaje dwie liczby rozstrzygające sprawę. Prędkość inferencji to liczba milisekund na detekcję; gdy rośnie ponad wartość z tabeli, akcelerator się dławi – Coral na USB, dostatecznie ciepły, by zwolnić, to w zamkniętej szafce widok znajomy. Liczba klatek detekcji to tempo faktycznie osiągane; gdy leży poniżej ustawionego, klatki trafiają do kolejki i są odrzucane.
Z zewnątrz obie usterki wyglądają tak samo, i to w sposób najmniej pomocny z możliwych: nagranie jest, oś czasu bez luk, a przy zdarzeniu po prostu nie wisi żaden obiekt. Nic nie padło głośno. Budżet był przekroczony przez cztery sekundy i były to dokładnie te cztery sekundy, na których zależało.
Konfiguracja detektorów i ograniczanie liczby obszarów
W konfiguracji Frigate Coral jest detektorem typu edgetpu, a wartość device wskazuje, które urządzenie Frigate otwiera: usb dla pojedynczego modułu USB, pci dla pojedynczej karty M.2 lub PCIe. Drugi akcelerator to po prostu drugi wpis z indeksem:
detectors:
coral1:
type: edgetpu
device: pci:0
coral2:
type: edgetpu
device: pci:1
Dla USB odpowiednie wartości to usb:0 i usb:1. Każdy detektor działa we własnym procesie, a wszystkie pobierają zadania z jednej wspólnej kolejki żądań detekcji napływających ze wszystkich kamer. Nie ma stałego przypisania kamer do akceleratorów, dlatego drugi Coral podnosi pułap całej instalacji, a nie tylko połowy kamer. W Dockerze Coral PCIe pojawia się na hoście po zainstalowaniu sterownika jako /dev/apex_0 i właśnie ten węzeł urządzenia jest przekazywany do kontenera.
Czynnikiem rachunku, który konfiguracja potrafi obniżyć bez utraty okazji do detekcji, jest liczba obszarów na klatkę. Bezpośrednio działają na niego dwie funkcje Frigate.
- Maski ruchu zakrywają obszary, w których ruch nigdy nie oznacza interesującego obiektu: własny znacznik czasu kamery, niebo, korony drzew na wietrze. Ruch wewnątrz maski nie uruchamia już detekcji, więc te miejsca przestają produkować obszary. Obiekt w zamaskowanym obszarze nadal zostaje wykryty, gdy detekcję uruchomi ruch w innym miejscu kadru. Nadmiar masek ma swoją cenę: obiekt, który przechodzi w całkowicie zamaskowany obszar, może zostać zgubiony i po ponownym pojawieniu się jest śledzony jako nowy.
- Obiekty nieruchome nie trafiają do detektora w każdej klatce. Gdy śledzony obiekt pozostaje niemal w tym samym miejscu przez próg bezruchu, domyślnie dziesięciokrotność liczby klatek detekcji (50 klatek przy 5 kl./s), Frigate sprawdza go już tylko co 50. klatkę, zgodnie z domyślnym interwałem. Samochód zaparkowany w kadrze jest wtedy sprawdzany mniej więcej co dziesięć sekund zamiast pięć razy na sekundę, dopóki ruch w obrębie samego obiektu nie przywróci zwykłej detekcji.
Oba efekty należą do mierzonego współczynnika obszarów z rachunku powyżej: miarodajna jest wartość obserwowana przy założonych maskach, a nie ta sprzed nich.
Pytania i odpowiedzi
Na ile odciąża Corala obniżenie liczby klatek detekcji z 5 do 3 na sekundę?
Proporcjonalnie: w przykładzie z ośmioma kamerami i 1,5 obszaru na klatkę z 60 inferencji na sekundę robi się 36, co przy 8 ms daje 288 zamiast 480 ms/s, czyli 29 zamiast 48 % jednego Corala. Ceną jest mniej okazji, bo osoba, która przechodzi przez kadr w ciągu sekundy, zostaje sprawdzona trzy razy zamiast pięciu, a obiekt widoczny w kadrze tylko przez chwilę łatwiej przeoczyć.
Po czym poznać, że Coral USB rzeczywiście pracuje z prędkością USB 3.0?
Sam niebieski kolor gniazda niczego nie dowodzi. Hub USB 2.0 po drodze, przedłużacz bez żył USB 3.0 albo niedociśnięta wtyczka, która styka się tylko z kontaktami USB 2.0, ograniczają moduł do 480 Mb/s. W Linuksie polecenie lsusb -t pokazuje wynegocjowaną prędkość każdego urządzenia: 5000M oznacza USB 3.0, a 480M – USB 2.0.
Rozstrzygająca jest prędkość inferencji podawana przez Frigate: około 8 ms oznacza szybką pracę, wartość w okolicach 22 ms wskazuje na wolniejsze połączenie. Przy Frigate w Dockerze dochodzi jeszcze jedna osobliwość: po załadowaniu oprogramowania układowego moduł zgłasza się na magistrali ponownie, pod innym identyfikatorem. Dlatego do kontenera trafia zwykle cała magistrala USB, a nie pojedyncze urządzenie.
Czy obciążenie dekodowaniem, którego nie przejmuje żaden Coral, da się przenieść na układ graficzny?
Tak, a przy kilku kamerach daje to często więcej niż drugi akcelerator. Frigate dekoduje za pomocą ffmpeg, a ffmpeg potrafi oddać tę pracę sprzętowi: w procesorach Intela zintegrowanej grafice przez VAAPI lub Quick Sync, w kartach Nvidia dekoderowi NVDEC, a w niektórych komputerach jednopłytkowych ich własnym dekoderom. W konfiguracji służą do tego hwaccel_args, dla których Frigate ma gotowe ustawienia (presety).
Do rachunku należą dwie uwagi. Po pierwsze, odciążenie dotyczy tylko strumienia, który faktycznie jest dekodowany, czyli podstrumienia do detekcji; strumień główny i tak jest tylko kopiowany. Podanie detekcji strumienia głównego 4K przenosi kosztowną pracę, zamiast jej uniknąć. Po drugie, dekodowanie i detekcja dzielą ten sam układ graficzny, jeśli działa na nim również OpenVINO jako detektor. Około 15 ms z tabeli nie jest wtedy pewnikiem; miarodajna jest prędkość inferencji, którą Frigate podaje pod obciążeniem.