Użycie jednostek procesora graficznego (GPU) do uruchamiania modeli uczenia maszynowego może znacznie poprawić wydajność modelu i wygodę użytkowników aplikacji korzystających z tego systemu. TensorFlow Lite umożliwia korzystanie z GPU i innych wyspecjalizowanych procesorów za pomocą sterownika sprzętowego o nazwie delegaty. Włączenie korzystania z GPU w aplikacjach TensorFlow Lite ML może przynieść te korzyści:
- Szybkość – GPU są tworzone z myślą o dużej przepustowości bardzo równoległych zadań. Taka konstrukcja sprawia, że dobrze nadają się do stosowania głębokich sieci neuronowych, które składają się z ogromnej liczby operatorów, z których każdy pracuje nad tensorami wejściowymi, które można przetwarzać równolegle, co zwykle skraca czas oczekiwania. W najlepszym przypadku uruchomienie modelu z GPU może działać wystarczająco szybko, by umożliwić działanie aplikacji w czasie rzeczywistym, które wcześniej nie były możliwe.
- Oszczędzanie energii – GPU wykonuje obliczenia związane z systemami uczącymi się w bardzo wydajny i zoptymalizowany sposób, zwykle zużywając mniej energii i generując mniej ciepła niż w przypadku tego samego zadania wykonywanego na procesorach.
Ten dokument zawiera omówienie obsługiwanych GPU w TensorFlow Lite i niektórych zaawansowanych zastosowań z procesorami GPU. Bardziej szczegółowe informacje o wdrażaniu obsługi GPU na konkretnych platformach znajdziesz w tych przewodnikach:
Obsługa operacji GPU ML
Istnieją pewne ograniczenia co do tego, jakie operacje (operacje TensorFlow ML) mogą być przyspieszone przez delegację GPU TensorFlow Lite. Delegat obsługuje te operacje z 16- 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 delegację GPU, platforma uruchomi tylko część grafu w GPU, a resztę na procesorze CPU. Ze względu na wysokie koszty synchronizacji CPU/GPU taki tryb podzielonego wykonywania kodu często powoduje wolniejsze działanie niż przy korzystaniu z samego procesora w całej sieci. W takim przypadku aplikacja wygeneruje ostrzeżenie, na przykład:
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 środowiska wykonawczego. Gdy testujesz wykonanie modelu z użyciem delegowanego GPU, musisz zwracać uwagę na te ostrzeżenia. Duża liczba tych ostrzeżeń może wskazywać, że Twój model nie najlepiej nadaje się do przyspieszania za pomocą GPU i może wymagać refaktoryzacji modelu.
Przykładowe modele
Te przykładowe modele zostały opracowane z myślą o wykorzystaniu akceleracji GPU za pomocą TensorFlow Lite i są dostępne do celów referencyjnych i testowania:
- Klasyfikacja obrazów MobileNet v1 (224 x 224)
- Model klasyfikacji obrazów przeznaczony do urządzeń mobilnych i wbudowanych aplikacji do rozpoznawania obrazów. (model)
- Segmentacja DeepLab
(257 x 257)
- model segmentacji obrazu, który przypisuje etykiety semantyczne, np. pies, kot czy samochód, do każdego piksela na obrazie wejściowym. (model)
- Wykrywanie obiektów na dysku SSD MobileNet
- Model klasyfikacji obrazów, który wykrywa wiele obiektów z ramkami ograniczającymi. (model)
- PoseNet do szacowania pozycji
- Model wizyjny, który szacuje pozycje ludzi na zdjęciach lub filmach. (model)
Optymalizacja pod kątem GPU
Opisane tu techniki mogą pomóc Ci uzyskać lepszą wydajność w przypadku uruchamiania modeli na sprzęcie GPU z wykorzystaniem delegacji GPU TensorFlow Lite:
Operacje zmiany kształtu – niektóre operacje, które są szybkie na procesorze, mogą wiązać się z wysokim kosztem GPU na urządzeniach mobilnych. Wykonywanie operacji zmiany kształtu jest szczególnie kosztowne, np.
BATCH_TO_SPACE
,SPACE_TO_BATCH
czySPACE_TO_DEPTH
. Trzeba 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ć skuteczność.Kanały danych obrazu – w przypadku GPU dane tensora są dzielone na 4 kanały, więc obliczenia na tensorze o kształcie
[B,H,W,5]
są mniej więcej takie same na tensorze o kształcie[B,H,W,8]
, ale znacznie gorzej niż[B,H,W,4]
. Jeśli używany aparat obsługuje ramki obrazu w formacie RGBA, przesyłanie obrazu z 4-kanałowego źródła danych jest znacznie szybsze, ponieważ pozwala uniknąć kopiowania z pamięci 3-kanałowej RGB na 4-kanałową RGBX.Modele zoptymalizowane pod kątem urządzeń mobilnych – aby uzyskać najlepszą skuteczność, spróbuj ponownie przetrenować klasyfikator z architekturą sieci zoptymalizowaną pod kątem urządzeń mobilnych. Optymalizacja pod kątem wnioskowania na urządzeniu może znacznie zmniejszyć czas oczekiwania i zużycie energii dzięki wykorzystaniu funkcji sprzętu mobilnego.
Zaawansowana obsługa GPU
Aby zapewnić jeszcze większą wydajność modeli, w tym kwantyzacji i serializacji, możesz użyć dodatkowych, zaawansowanych technik przetwarzania GPU. W sekcjach poniżej szczegółowo opisujemy te metody.
Korzystanie z modeli kwantowych
W tej sekcji wyjaśniamy, jak delegowany GPU przyspiesza 8-bitowe modele kwantyzowane, w tym:
- Modele wytrenowane z użyciem trenowania z uwzględnieniem kwantyzacji
- Kwantyzacja zakresu dynamicznego po zakończeniu trenowania
- kwantyzacja w pełni po zakończeniu trenowania
Aby zoptymalizować wydajność, używaj modeli zawierających zarówno zmiennoprzecinkowe tensory wejściowe i wyjściowe.
Jak to działa?
Backend GPU obsługuje tylko wykonywanie zmiennoprzecinkowe, dlatego uruchamiamy kwantyzowane modele, zapewniając mu „widok zmiennoprzecinkowy” oryginalnego modelu. Ogólnie obejmuje to te czynności:
Tensory stałe (np. wagi/odchylenia) są dekwantyzowane raz do pamięci GPU. Ta operacja ma miejsce, gdy delegat jest włączony w TensorFlow Lite.
Dane wejściowe i wyjściowe do programu GPU, w przypadku kwantyzacji 8-bitowej, są dekwantyzowane i (odpowiednio) poddane kwantyzacji w przypadku każdego wnioskowania. Ta operacja jest wykonywana na CPU z użyciem zoptymalizowanych jąder TensorFlow Lite.
Symulatory kwantyzacji są umieszczane między operacjami, aby naśladować poddane kwantyzacji zachowanie. To podejście jest konieczne w przypadku modeli, w których operatorzy oczekują, że aktywacje będą spełniać granice ustalone podczas kwantyzacji.
Informacje o włączaniu tej funkcji z użyciem delegata GPU znajdziesz w tych artykułach:
- korzystanie z modeli poddanych kwantyzacji z GPU na Androidzie;
- Korzystanie z modeli kwantowych z GPU w iOS
Skrócenie czasu inicjowania za pomocą serializacji
Funkcja przekazywania dostępu do GPU umożliwia wczytywanie ze wstępnie skompilowanego kodu jądra oraz zserializowanych i zapisanych na dysku danych modelu z poprzednich uruchomień. Takie podejście pozwala uniknąć ponownej kompilacji i może skrócić czas uruchamiania nawet o 90%. Jest to możliwe dzięki zamianie miejsca na dysku w celu zaoszczędzenia czasu. Możesz włączyć tę funkcję, wybierając kilka 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 użyj parametru
getCodeCacheDir()
, który wskazuje lokalizację, która jest prywatna dla bieżącej aplikacji. - Token modelu musi być unikalny dla urządzenia w przypadku danego modelu. Token modelu możesz obliczyć, generując odcisk cyfrowy z danych modelu za pomocą bibliotek takich jak
farmhash::Fingerprint64
.