Używanie jednostek przetwarzania grafiki (GPU) do uruchamiania modeli uczenia maszynowego (ML) może znacznie poprawić wydajność modelu i wrażenia użytkownika aplikacji obsługujących ML. TensorFlow Lite umożliwia korzystanie z GPU i innych wyspecjalizowanych procesorów poprzez sterownik sprzętowy zwany delegatami . Włączenie użycia procesorów graficznych z aplikacjami TensorFlow Lite ML może zapewnić następujące korzyści:
- Szybkość — procesory graficzne są zbudowane z myślą o wysokiej przepustowości masowo równoległych obciążeń. 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 zwykle skutkuje mniejszym opóźnieniem. W najlepszym scenariuszu uruchomienie modelu na GPU może działać wystarczająco szybko, aby włączyć aplikacje działające w czasie rzeczywistym, które wcześniej nie były możliwe.
- Efektywność energetyczna — procesory graficzne 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 uruchomione na procesorach.
Ten dokument zawiera przegląd obsługi procesorów graficznych 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 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
-
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, framework uruchomi tylko część wykresu na GPU, a pozostałą część na CPU. Ze względu na wysoki koszt synchronizacji procesora/procesora, taki dzielony tryb 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.
Nie ma wywołania zwrotnego dla błędów tego typu, ponieważ nie jest to rzeczywisty błąd w czasie wykonywania. Podczas testowania wykonania modelu za pomocą delegata GPU należy zwrócić uwagę na te ostrzeżenia. Duża liczba tych ostrzeżeń może wskazywać, że Twój model nie jest najlepiej przystosowany do przyspieszania 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ą udostępniane w celach informacyjnych i testowych:
- Klasyfikacja obrazów MobileNet v1 (224x224) — model klasyfikacji obrazów zaprojektowany dla mobilnych i wbudowanych aplikacji wizyjnych. ( model )
- Segmentacja DeepLab (257x257) - model segmentacji obrazu, który przypisuje etykiety semantyczne, takie jak pies, kot, samochód, do każdego piksela w obrazie wejściowym. ( model )
- Wykrywanie obiektów MobileNet SSD — model klasyfikacji obrazów, który wykrywa wiele obiektów z ramkami ograniczającymi. ( model )
- PoseNet do szacowania pozy — model wizyjny, który szacuje pozy osób na obrazie lub filmie. ( model )
Optymalizacja pod kątem GPU
Poniższe techniki mogą pomóc w uzyskaniu lepszej wydajności podczas uruchamiania modeli na sprzęcie GPU przy użyciu delegata TensorFlow Lite GPU:
Operacje zmiany kształtu — niektóre operacje, które są szybkie na procesorze, mogą wiązać się z wysokimi kosztami procesora graficznego na urządzeniach mobilnych. Operacje zmiany kształtu są szczególnie kosztowne w obsłudze, 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 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, więc 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 używany sprzęt kamery obsługuje ramki obrazów w RGBA, podawanie 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 szkolenie klasyfikatora przy użyciu architektury sieci zoptymalizowanej pod kątem urządzeń mobilnych. Optymalizacja pod kątem wnioskowania na urządzeniu może znacznie 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ść modeli, w tym kwantyzację i serializację. 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 8-bitowe modele skwantowane, w tym:
- Modele przeszkolone w ramach szkolenia uwzględniającego kwantyzację
- Kwantyzacja zakresu dynamicznego po treningu
- Kwantyzacja całkowitoliczbowa po treningu
Aby zoptymalizować wydajność, użyj modeli, które mają zarówno zmiennoprzecinkowe tensory wejściowe, jak i wyjściowe.
Jak to działa?
Ponieważ backend GPU obsługuje tylko wykonanie zmiennoprzecinkowe, uruchamiamy modele skwantowane, nadając im „widok zmiennoprzecinkowy” oryginalnego modelu. Na wysokim poziomie wiąże się to z następującymi krokami:
Tensory stałe (takie jak wagi/obciążenia) są raz dekwantowane do pamięci GPU. Ta operacja ma miejsce, gdy delegat jest włączony dla TensorFlow Lite.
Wejścia i wyjścia programu GPU, jeśli są skwantowane 8-bitowo, są dekwantyzowane i skwantyzowane (odpowiednio) dla każdego wnioskowania. Ta operacja jest wykonywana na procesorze przy użyciu zoptymalizowanych jąder TensorFlow Lite.
Symulatory kwantyzacji są umieszczane między operacjami, aby naśladować skwantowane zachowanie. Takie podejście jest konieczne w przypadku modeli, w których operacje oczekują, że aktywacje będą podążać za ograniczeniami wyuczonymi podczas kwantyzacji.
Aby uzyskać informacje na temat włączania tej funkcji za pomocą delegata GPU, zobacz następujące informacje:
- Korzystanie ze skwantowanych modeli z GPU w systemie Android
- Używanie modeli skwantyzowanych z GPU na iOS
Skrócenie czasu inicjalizacji dzięki serializacji
Funkcja delegata 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%. Ta poprawa jest osiągana poprzez wymianę miejsca na dysku w celu zaoszczędzenia czasu. Możesz włączyć tę funkcję za pomocą kilku opcji konfiguracji, jak pokazano w następujących 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 kod jest zgodny z tymi regułami implementacji:
- Przechowuj dane serializacji w katalogu, który nie jest dostępny dla innych aplikacji. Na urządzeniach z systemem Android użyj
getCodeCacheDir()
, która wskazuje lokalizację prywatną dla bieżącej aplikacji. - Token modelu musi być unikalny dla urządzenia dla konkretnego modelu. Możesz obliczyć token modelu, generując odcisk palca z danych modelu przy użyciu bibliotek, takich jak
farmhash::Fingerprint64
.