Korzystanie z procesorów graficznych (GPU) do uruchamiania modeli uczenia maszynowego (ML) może radykalnie poprawić wydajność modelu i wygodę użytkownika aplikacji obsługujących uczenie maszynowe. TensorFlow Lite umożliwia korzystanie z procesorów graficznych i innych wyspecjalizowanych procesorów za pośrednictwem sterowników sprzętowych zwanych delegatami . Umożliwienie korzystania z procesorów graficznych w aplikacjach TensorFlow Lite ML może zapewnić następujące korzyści:
- Szybkość — układy GPU zostały stworzone z myślą o wysokiej przepustowości masowo równoległych obciążeń. Taka konstrukcja sprawia, że doskonale 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 GPU może działać wystarczająco szybko, aby umożliwić działanie aplikacji w czasie rzeczywistym, które wcześniej nie były możliwe.
- Efektywność energetyczna — GPU wykonują obliczenia ML w bardzo wydajny i zoptymalizowany sposób, zwykle zużywając mniej energii i generując mniej ciepła niż to samo zadanie wykonywane na procesorach.
Ten dokument zawiera omówienie obsługi GPU w TensorFlow Lite oraz niektóre zaawansowane zastosowania procesorów GPU. Aby uzyskać bardziej szczegółowe informacje na temat wdrażania obsługi GPU na określonych platformach, zapoznaj się z następującymi przewodnikami:
Obsługa operacji GPU ML
Istnieją pewne ograniczenia dotyczące tego, jakie operacje TensorFlow ML lub ops 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, struktura uruchomi tylko część wykresu na GPU, a pozostałą część na CPU. Ze względu na wysoki koszt synchronizacji CPU/GPU, taki tryb podzielonego wykonywania często skutkuje mniejszą wydajnością niż wtedy, gdy cała sieć działa na samym CPU. W takim przypadku aplikacja generuje ostrzeżenie, takie jak:
WARNING: op code #42 cannot be handled by this delegate.
Nie ma wywołania zwrotnego w przypadku awarii tego typu, ponieważ nie jest to rzeczywista awaria w czasie wykonywania. Podczas testowania wykonania modelu za pomocą delegata procesora GPU należy zwracać uwagę na te ostrzeżenia. Duża liczba tych ostrzeżeń może oznaczać, że model nie jest najlepiej przystosowany do akceleracji GPU i może wymagać refaktoryzacji modelu.
Przykładowe modele
Poniższe przykładowe modele zostały zbudowane w celu wykorzystania akceleracji GPU za pomocą TensorFlow Lite i są dostępne w celach informacyjnych i testowych:
- Klasyfikacja obrazu MobileNet v1 (224x224) — model klasyfikacji obrazu przeznaczony dla mobilnych i osadzonych aplikacji wizyjnych. ( modelka )
- Segmentacja DeepLab (257x257) — model segmentacji obrazu, który przypisuje etykiety semantyczne, takie jak pies, kot, samochód, do każdego piksela obrazu wejściowego. ( modelka )
- Wykrywanie obiektów MobileNet SSD — model klasyfikacji obrazów, który wykrywa wiele obiektów z ramkami ograniczającymi. ( modelka )
- PoseNet do szacowania pozycji — model wizyjny, który szacuje pozy ludzi na obrazach lub filmach. ( modelka )
Optymalizacja pod GPU
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, które obciążają procesor, mogą wiązać się z wysokimi kosztami dla procesora graficznego na urządzeniach mobilnych. Operacje przekształcania są szczególnie kosztowne w uruchomieniu, w tym
BATCH_TO_SPACE
,SPACE_TO_BATCH
,SPACE_TO_DEPTH
i tak dalej. Należy dokładnie przeanalizować użycie operacji zmiany kształtu i wziąć pod uwagę, że mogły one zostać zastosowane tylko do eksploracji danych lub do wczesnych iteracji modelu. Usunięcie ich może znacznie poprawić wydajność.Kanały danych obrazu — na GPU dane tensorowe są dzielone na 4 kanały, więc obliczenia na tensorze o kształcie
[B,H,W,5]
działają mniej więcej tak samo na tensorze o kształcie[B,H,W,8]
, ale znacznie gorszy niż[B,H,W,4]
. Jeśli używany sprzęt kamery obsługuje ramki obrazu w RGBA, podawanie tego 4-kanałowego wejścia 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 kwantyzacji i serializacji. Poniższe sekcje opisują te techniki bardziej szczegółowo.
Korzystanie z modeli skwantowanych
W tej sekcji wyjaśniono, w jaki sposób delegat GPU przyspiesza skwantyzowane 8-bitowe modele, w tym:
- Modele przeszkolone za pomocą treningu uwzględniającego kwantyzację
- Kwantyzacja zakresu dynamicznego po treningu
- Kwantyzacja pełnych liczb całkowitych po szkoleniu
Aby zoptymalizować wydajność, użyj modeli, które mają zmiennoprzecinkowe tensory wejściowe i wyjściowe.
Jak to działa?
Ponieważ zaplecze GPU obsługuje tylko wykonywanie zmiennoprzecinkowe, uruchamiamy kwantyzowane modele, dając im „widok zmiennoprzecinkowy” oryginalnego modelu. Na wysokim poziomie obejmuje to następujące kroki:
Stałe tensory (takie jak wagi/odchylenia) są raz dekwantyzowane 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ą skwantyzowane 8-bitowo, są dekwantowane 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 między operacjami, aby naśladować skwantyzowane zachowanie. Takie podejście jest konieczne w przypadku modeli, w których operatorzy oczekują, że aktywacje będą zgodne z granicami poznanymi podczas kwantyzacji.
Aby uzyskać informacje na temat włączania tej funkcji z pełnomocnikiem GPU, zobacz następujące informacje:
- Używanie skwantyzowanych modeli z procesorem graficznym w systemie Android
- Używanie skwantyzowanych modeli 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 zapisywanych na dysku z poprzednich uruchomień. Takie podejście pozwala uniknąć ponownej kompilacji i może skrócić czas uruchamiania nawet o 90%. Poprawę tę uzyskuje 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);
Podczas korzystania z funkcji serializacji upewnij się, że Twój kod jest zgodny z następującymi zasadami implementacji:
- Przechowuj dane serializacji w katalogu niedostępnym 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 określonego modelu. Token modelu można obliczyć, generując odcisk palca z danych modelu przy użyciu bibliotek, takich jak
farmhash::Fingerprint64
.