Delegaci GPU dla TensorFlow Lite

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:

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:

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:

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 .