Używanie jednostek przetwarzania grafiki (GPU) do uruchamiania modeli uczenia maszynowego (ML) może radykalnie poprawić wydajność modelu i komfort korzystania z aplikacji obsługujących technologię ML. TensorFlow Lite umożliwia korzystanie z procesorów graficznych i innych wyspecjalizowanych procesorów za pośrednictwem sterownika sprzętowego zwanego delegatami . Włączenie korzystania z procesorów graficznych w aplikacjach TensorFlow Lite ML może zapewnić następujące korzyści:
- Szybkość — procesory graficzne są zbudowane z myślą o dużej przepustowości przy masowo równoległych obciążeniach. Taka konstrukcja sprawia, że dobrze nadają się do głębokich sieci neuronowych, które składają się z ogromnej liczby operatorów, z których każdy pracuje na tensorach wejściowych, które mogą być przetwarzane równolegle, co zazwyczaj skutkuje mniejszymi opóźnieniami. W najlepszym scenariuszu uruchomienie modelu na procesorze graficznym może działać wystarczająco szybko, aby umożliwić działanie aplikacji w czasie rzeczywistym, co wcześniej nie było możliwe.
- Efektywność energetyczna — procesory graficzne wykonują obliczenia ML w bardzo wydajny i zoptymalizowany sposób, zazwyczaj zużywając mniej energii i generując mniej ciepła niż to samo zadanie uruchamiane na procesorach.
Ten dokument zawiera przegląd obsługi procesorów graficznych w TensorFlow Lite oraz niektóre zaawansowane zastosowania procesorów GPU. Bardziej szczegółowe informacje na temat wdrażania obsługi procesorów graficznych na określonych platformach można znaleźć w następujących przewodnikach:
Obsługa operacji GPU ML
Istnieją pewne ograniczenia dotyczące operacji TensorFlow ML ( ops) , które mogą być przyspieszane przez delegata procesora GPU TensorFlow Lite. Delegat obsługuje następujące operacje z 16-bitową i 32-bitową precyzją zmiennoprzecinkową:
-
ADD
-
AVERAGE_POOL_2D
-
CONCATENATION
-
CONV_2D
-
DEPTHWISE_CONV_2D v1-2
-
EXP
-
FULLY_CONNECTED
-
LOGICAL_AND
-
LOGISTIC
-
LSTM v2 (Basic LSTM only)
-
MAX_POOL_2D
-
MAXIMUM
-
MINIMUM
-
MUL
-
PAD
-
PRELU
-
RELU
-
RELU6
-
RESHAPE
-
RESIZE_BILINEAR v1-3
-
SOFTMAX
-
STRIDED_SLICE
-
SUB
-
TRANSPOSE_CONV
Domyślnie wszystkie operacje są obsługiwane tylko w wersji 1. Włączenie obsługi kwantyzacji włącza odpowiednie wersje, na przykład ADD v2.
Rozwiązywanie problemów z obsługą GPU
Jeśli niektóre operacje nie są obsługiwane przez delegata GPU, platforma uruchomi tylko część wykresu na GPU, a pozostałą część na CPU. Ze względu na wysoki koszt synchronizacji CPU/GPU, taki tryb rozdzielonego wykonywania często skutkuje niższą wydajnością niż wtedy, gdy cała sieć działa na samym procesorze. W takim przypadku aplikacja generuje ostrzeżenie, takie jak:
WARNING: op code #42 cannot be handled by this delegate.
W przypadku awarii tego typu nie ma wywołania zwrotnego, ponieważ nie jest to rzeczywista awaria w czasie wykonywania. Podczas testowania wykonania modelu z delegatem procesora GPU należy zwrócić uwagę na te ostrzeżenia. Duża liczba tych ostrzeżeń może wskazywać, że Twój model nie nadaje się najlepiej do użycia z akceleracją GPU i może wymagać refaktoryzacji modelu.
Przykładowe modele
Poniższe przykładowe modele zostały zbudowane tak, aby wykorzystywać akcelerację GPU za pomocą TensorFlow Lite i są udostępniane w celach informacyjnych i testowych:
- Klasyfikacja obrazów MobileNet v1 (224x224) — model klasyfikacji obrazów przeznaczony dla aplikacji wizyjnych mobilnych i wbudowanych. ( Model )
- Segmentacja DeepLab (257x257) - model segmentacji obrazu, który przypisuje każdemu pikselowi obrazu wejściowego etykiety semantyczne, takie jak pies, kot, samochód. ( Model )
- Wykrywanie obiektów MobileNet SSD — model klasyfikacji obrazu, który wykrywa wiele obiektów z ramkami ograniczającymi. ( Model )
- PoseNet do szacowania pozy — model wizyjny, który ocenia pozy ludzi na obrazie lub filmie. ( Model )
Optymalizacja pod kątem procesorów graficznych
Poniższe techniki mogą pomóc w uzyskaniu lepszej wydajności podczas uruchamiania modeli na sprzęcie GPU przy użyciu delegata GPU TensorFlow Lite:
Operacje zmiany kształtu — niektóre operacje wymagające szybkiego wykorzystania procesora mogą wiązać się z wysokimi kosztami dla procesora graficznego w urządzeniach mobilnych. Operacje zmiany kształtu są szczególnie kosztowne w wykonaniu, w tym
BATCH_TO_SPACE
,SPACE_TO_BATCH
,SPACE_TO_DEPTH
i tak dalej. Powinieneś dokładnie sprawdzić użycie operacji zmiany kształtu i wziąć pod uwagę, że można je zastosować tylko do eksploracji danych lub do wczesnych iteracji modelu. Usunięcie ich może znacznie poprawić wydajność.Kanały danych obrazu — na GPU dane tensora są dzielone na 4 kanały, zatem obliczenia na tensorze o kształcie
[B,H,W,5]
działają mniej więcej tak samo na tensorze kształtu[B,H,W,8]
, ale znacznie gorzej niż[B,H,W,4]
. Jeśli sprzęt kamery, którego używasz, obsługuje klatki obrazu w RGBA, dostarczanie 4-kanałowego sygnału wejściowego jest znacznie szybsze, ponieważ pozwala uniknąć kopiowania pamięci z 3-kanałowego RGB do 4-kanałowego RGBX.Modele zoptymalizowane pod kątem urządzeń mobilnych — aby uzyskać najlepszą wydajność, należy rozważyć ponowne przeszkolenie klasyfikatora przy użyciu architektury sieci zoptymalizowanej pod kątem urządzeń mobilnych. Optymalizacja pod kątem wnioskowania na urządzeniu może radykalnie zmniejszyć opóźnienia i zużycie energii dzięki wykorzystaniu funkcji sprzętu mobilnego.
Zaawansowana obsługa GPU
Możesz użyć dodatkowych, zaawansowanych technik przetwarzania GPU, aby zapewnić jeszcze lepszą wydajność swoich modeli, w tym kwantyzację i serializację. W poniższych sekcjach opisano te techniki bardziej szczegółowo.
Korzystanie z modeli skwantowanych
W tej sekcji wyjaśniono, w jaki sposób delegat GPU przyspiesza 8-bitowe modele kwantyzowane, w tym następujące:
- Modele przeszkolone w ramach szkolenia uwzględniającego kwantyzację
- Kwantyzacja zakresu dynamicznego po treningu
- Pełna kwantyzacja całkowitoliczbowa po treningu
Aby zoptymalizować wydajność, użyj modeli, które mają zarówno zmiennoprzecinkowy tensor wejściowy, jak i wyjściowy.
Jak to działa?
Ponieważ zaplecze GPU obsługuje tylko wykonywanie zmiennoprzecinkowe, uruchamiamy modele skwantowane, dając mu „widok zmiennoprzecinkowy” oryginalnego modelu. Na wysokim poziomie obejmuje to następujące kroki:
Stałe tensory (takie jak wagi/odchylenie) są dekwantyzowane po umieszczeniu w pamięci GPU. Ta operacja ma miejsce, gdy delegat jest włączony dla TensorFlow Lite.
Wejścia i wyjścia do programu GPU, jeśli są skwantowane 8-bitowo, są dekwantyzowane i kwantyzowane (odpowiednio) dla każdego wnioskowania. Ta operacja jest wykonywana na procesorze przy użyciu zoptymalizowanych jąder TensorFlow Lite.
Symulatory kwantyzacji są wstawiane pomiędzy operacjami, aby naśladować zachowanie skwantowane. Takie podejście jest konieczne w przypadku modeli, w których operatorzy oczekują, że aktywacje będą zgodne z granicami poznanymi podczas kwantyzacji.
Informacje na temat włączania tej funkcji za pomocą delegata GPU można znaleźć w następujących sekcjach:
- Korzystanie z modeli skwantowanych z procesorem graficznym w systemie Android
- Korzystanie z modeli skwantowanych z procesorem graficznym w systemie iOS
Skrócenie czasu inicjalizacji dzięki serializacji
Funkcja delegowania GPU umożliwia ładowanie ze wstępnie skompilowanego kodu jądra i danych modelu serializowanych i zapisanych na dysku z poprzednich uruchomień. Takie podejście pozwala uniknąć ponownej kompilacji i może skrócić czas uruchamiania nawet o 90%. Poprawę tę osiąga się poprzez wymianę miejsca na dysku w celu zaoszczędzenia czasu. Możesz włączyć tę funkcję za pomocą kilku opcji konfiguracji, jak pokazano w poniższych przykładach kodu:
C++
TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default(); options.experimental_flags |= TFLITE_GPU_EXPERIMENTAL_FLAGS_ENABLE_SERIALIZATION; options.serialization_dir = kTmpDir; options.model_token = kModelToken; auto* delegate = TfLiteGpuDelegateV2Create(options); if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;
Jawa
GpuDelegate delegate = new GpuDelegate( new GpuDelegate.Options().setSerializationParams( /* serializationDir= */ serializationDir, /* modelToken= */ modelToken)); Interpreter.Options options = (new Interpreter.Options()).addDelegate(delegate);
Korzystając z funkcji serializacji, upewnij się, że Twój kod jest zgodny z następującymi zasadami implementacji:
- Przechowuj dane serializacji w katalogu, który nie jest dostępny dla innych aplikacji. Na urządzeniach z Androidem użyj
getCodeCacheDir()
, która wskazuje lokalizację prywatną dla bieżącej aplikacji. - Token modelu musi być unikalny dla urządzenia dla konkretnego modelu. Można obliczyć token modelu, generując odcisk palca z danych modelu przy użyciu bibliotek takich jak
farmhash::Fingerprint64
.