Zastosowanie procesorów graficznych (GPU) do uruchamiania modeli systemów uczących się może znacznie zwiększyć wydajność modelu i wygodę użytkowników aplikacji obsługujących systemy uczące się. TensorFlow Lite umożliwia korzystanie z procesorów graficznych i innych wyspecjalizowanych procesorów za pomocą sterownika sprzętowego nazywanego delegates. Włączenie procesorów graficznych w aplikacjach TensorFlow Lite ML może przynieść te korzyści:
- Szybkość – procesory graficzne są zaprojektowane z myślą o dużej przepustowości przy masowo równoległych zadaniach. Taka konstrukcja sprawia, że są one szczególnie przydatne w przypadku głębokich sieci neuronowych, które składają się z dużej liczby operatorów. Każdy z nich pracuje na tensorach wejściowych, które można przetwarzać równolegle, co zwykle skraca czas oczekiwania. W najlepszym przypadku uruchomienie modelu na GPU może działać z wystarczającą szybkością, aby umożliwić działanie aplikacji w czasie rzeczywistym, które wcześniej nie były możliwe.
- Wydajność energetyczna – procesory graficzne wykonują obliczenia za pomocą systemów uczących się w bardzo skuteczny 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 omówienie obsługiwanych GPU w TensorFlow Lite, a także niektóre zaawansowane zastosowania procesorów GPU. Więcej informacji o wdrażaniu obsługi GPU na określonych platformach znajdziesz w tych przewodnikach:
Obsługa operacji GPU ML
Istnieją pewne ograniczenia dotyczące operacji, czyli operacji TensorFlow ML, które mogą być przyspieszane przez delegata GPU TensorFlow Lite. Delegat obsługuje te 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, np. DODAJ wersję 2.
Rozwiązywanie problemów z obsługą GPU
Jeśli niektóre działania nie są obsługiwane przez delegata GPU, platforma uruchomi tylko część wykresu na GPU, a pozostałą część na procesorze. Ze względu na wysokie koszty synchronizacji CPU/GPU taki tryb podzielonego wykonywania często powoduje wolniejsze działanie niż 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 błędów tego typu nie ma wywołania zwrotnego, ponieważ nie jest to rzeczywisty błąd podczas działania. Zwracaj uwagę na te ostrzeżenia, testując wykonanie modelu z osobą z przekazanym dostępem do GPU. Duża liczba tych ostrzeżeń może oznaczać, że Twój model nie najlepiej nadaje się do akceleracji GPU i może wymagać refaktoryzacji modelu.
Przykładowe modele
Poniższe przykładowe modele zostały utworzone z myślą o korzystaniu z akceleracji GPU w przypadku TensorFlow Lite i są udostępnione w celach informacyjnych i testowych:
- Klasyfikacja obrazów MobileNet w wersji 1 (224 x 224) – model klasyfikacji obrazów zaprojektowany z myślą o aplikacjach do rozpoznawania obrazów na urządzeniach mobilnych i w zasobach osadzonych. (model)
- Podział na segmenty w DeepLab (257 x 257) – model podziału obrazów na segmenty, który przypisuje do każdego piksela w obrazie wejściowym etykiety semantyczne, takie jak pies, kot czy samochód. (model)
- Wykrywanie obiektów SSD MobileNet – model klasyfikacji obrazów, który wykrywa wiele obiektów z ramkami ograniczającymi. (model)
- PoseNet do szacowania pozycji – model rozpoznawania obrazu służący do szacowania pozycji osób na zdjęciach lub w filmach. (model)
Optymalizuję pod kątem GPU
Poniższe techniki mogą pomóc w uzyskaniu lepszej wydajności podczas uruchamiania modeli na sprzęcie GPU z użyciem delegata GPU TensorFlow Lite:
Zmiana kształtu operacji – niektóre operacje, które są szybkie na procesorach, mogą powodować wysokie koszty GPU na urządzeniach mobilnych. Operacje zmiany kształtu są szczególnie kosztowne, takie jak
BATCH_TO_SPACE
,SPACE_TO_BATCH
,SPACE_TO_DEPTH
itp. Musisz uważnie przyjrzeć się wykorzystaniu operacji zmiany kształtu i zastanów się, że mogły one zostać zastosowane tylko do eksploracji danych lub we wczesnych iteracjach modelu. Ich usunięcie może znacznie poprawić wydajność.Kanały danych obrazu – w przypadku GPU dane tensora są podzielone na 4 kanały, więc obliczenia na tensorze o kształcie
[B,H,W,5]
dają podobne wyniki w przypadku tensora kształtu[B,H,W,8]
, ale znacznie gorsze niż w przypadku elementu[B,H,W,4]
. Jeśli używany aparat obsługuje klatki obrazu w formacie RGBA, przesyłanie obrazu z 4-kanałowego wejścia odbywa się znacznie szybciej, ponieważ unikamy kopiowania pamięci z 3-kanałowego RGB na 4-kanałowy RGBX.Modele zoptymalizowane pod kątem urządzeń mobilnych – aby uzyskać najlepszą skuteczność, spróbuj ponownie wytrenować klasyfikator, korzystając z architektury sieci zoptymalizowanej pod kątem urządzeń mobilnych. Dzięki wykorzystaniu funkcji sprzętu mobilnego optymalizacja pod kątem wnioskowania na urządzeniu może znacznie zmniejszyć opóźnienia i zużycie energii.
Zaawansowana obsługa GPU
W przypadku przetwarzania GPU możesz korzystać z dodatkowych, zaawansowanych metod, aby zapewnić jeszcze lepszą wydajność modeli, w tym kwantyzację i serializację. W poniższych sekcjach szczegółowo opisano te techniki.
Używanie modeli kwantyzowanych
W tej sekcji wyjaśniamy, jak delegat GPU przyspiesza 8-bitowe modele poddane kwantyzacji, w tym:
- Modele wytrenowane z wykorzystaniem trenowania z uwzględnieniem kwantyzacji
- Kwantyfikacja zakresu dynamicznego po zakończeniu trenowania
- Kwantyzacja pełnej liczby całkowitej po zakończeniu trenowania
Aby zoptymalizować wydajność, używaj modeli zawierających zarówno tensory wejściowe i wyjściowe, jak i zmiennoprzecinkowe.
Jak to działa?
Backend GPU obsługuje tylko wykonywanie zmiennoprzecinkowe, więc uruchamiamy modele poddane kwantyzacji, nadając mu „widok zmiennoprzecinkowy” oryginalnego modelu. Ogólnie oznacza to, że:
Tensory stałe (np. wagi/odchylenia) są dekwantyzowane raz w pamięci GPU. Ta operacja ma miejsce, gdy delegat jest włączony dla TensorFlow Lite.
Dane wejściowe i wyjściowe przesyłane do programu GPU, jeśli 8-bitowe dane są poddawane kwantyzacji, są poddawane kwantyzacji i kwantyzowane (odpowiednio) w przypadku każdego wnioskowania. Ta operacja jest wykonywana na procesorze za pomocą zoptymalizowanych jąder TensorFlow Lite.
Symulatory kwantyzacji są wstawiane między operacjami, aby naśladować zachowanie skwantyzowane. To podejście jest niezbędne w przypadku modeli, w przypadku których operacje oczekują, że aktywacje będą zgodne z granicami ustalonymi podczas kwantyzacji.
Informacje o włączaniu tej funkcji za pomocą delegata GPU znajdziesz w tych artykułach:
- Korzystanie z kwantyzowanych modeli z GPU na Androidzie
- Korzystanie z kwantyzowanych modeli z GPU w iOS
Skrócenie czasu inicjowania dzięki serializacji
Funkcja delegowania GPU umożliwia wczytywanie ze wstępnie skompilowanego kodu jądra oraz danych modelu zserializowanych i zapisanych na dysku z poprzednich uruchomień. To podejście pozwala uniknąć ponownej kompilacji i skrócić czas uruchamiania nawet o 90%. Jest to możliwe dzięki zamianie miejsca na dysku na oszczędzanie czasu. Możesz włączyć tę funkcję za pomocą kilku opcji konfiguracji, tak jak w tych 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;
Java
GpuDelegate delegate = new GpuDelegate( new GpuDelegate.Options().setSerializationParams( /* serializationDir= */ serializationDir, /* modelToken= */ modelToken)); Interpreter.Options options = (new Interpreter.Options()).addDelegate(delegate);
Jeśli korzystasz z funkcji serializacji, upewnij się, że Twój 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 Androidem parametr
getCodeCacheDir()
wskazuje lokalizację, która jest prywatna dla bieżącej aplikacji. - Token modelu musi być unikalny dla urządzenia konkretnego modelu. Token modelu możesz obliczyć, generując odcisk cyfrowy na podstawie danych modelu za pomocą bibliotek takich jak
farmhash::Fingerprint64
.