Delegaci GPU dla TensorFlow Lite

Używanie jednostek przetwarzania grafiki (GPU) do uruchamiania modeli uczenia maszynowego (ML) może radykalnie poprawić wydajność modelu i komfort korzystania z aplikacji obsługujących technologię ML. TensorFlow Lite umożliwia korzystanie z procesorów graficznych i innych wyspecjalizowanych procesorów za pośrednictwem sterownika sprzętowego zwanego delegatami . Włączenie korzystania z procesorów graficznych w aplikacjach TensorFlow Lite ML może zapewnić następujące korzyści:

  • Szybkość — procesory graficzne są zbudowane z myślą o dużej przepustowości przy masowo równoległych obciążeniach. 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 zazwyczaj skutkuje mniejszymi opóźnieniami. W najlepszym scenariuszu uruchomienie modelu na procesorze graficznym może działać wystarczająco szybko, aby umożliwić działanie aplikacji w czasie rzeczywistym, co wcześniej nie było możliwe.
  • Efektywność energetyczna — procesory graficzne wykonują obliczenia ML w bardzo wydajny i zoptymalizowany sposób, zazwyczaj zużywając mniej energii i generując mniej ciepła niż to samo zadanie uruchamiane na procesorach.

Ten dokument zawiera przegląd obsługi procesorów graficznych w TensorFlow Lite oraz niektóre zaawansowane zastosowania procesorów GPU. Bardziej szczegółowe informacje na temat wdrażania obsługi procesorów graficznych na określonych platformach można znaleźć w następujących przewodnikach:

Obsługa operacji GPU ML

Istnieją pewne ograniczenia dotyczące operacji TensorFlow ML ( ops) , które 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, platforma uruchomi tylko część wykresu na GPU, a pozostałą część na CPU. Ze względu na wysoki koszt synchronizacji CPU/GPU, taki tryb rozdzielonego 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.

W przypadku awarii tego typu nie ma wywołania zwrotnego, ponieważ nie jest to rzeczywista awaria w czasie wykonywania. Podczas testowania wykonania modelu z delegatem procesora GPU należy zwrócić uwagę na te ostrzeżenia. Duża liczba tych ostrzeżeń może wskazywać, że Twój model nie nadaje się najlepiej do użycia z akceleracją GPU i może wymagać refaktoryzacji modelu.

Przykładowe modele

Poniższe przykładowe modele zostały zbudowane tak, aby wykorzystywać akcelerację GPU za pomocą TensorFlow Lite i są udostępniane w celach informacyjnych i testowych:

Optymalizacja pod kątem procesorów graficznych

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 wymagające szybkiego wykorzystania procesora mogą wiązać się z wysokimi kosztami dla procesora graficznego w urządzeniach mobilnych. Operacje zmiany kształtu są szczególnie kosztowne w wykonaniu, w tym BATCH_TO_SPACE , SPACE_TO_BATCH , SPACE_TO_DEPTH i tak dalej. Powinieneś dokładnie sprawdzić użycie operacji zmiany kształtu i wziąć pod uwagę, że można je zastosować tylko do eksploracji danych lub do 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, zatem 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 sprzęt kamery, którego używasz, obsługuje klatki obrazu w RGBA, dostarczanie 4-kanałowego sygnału wejściowego 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 kwantyzację i serializację. W poniższych sekcjach opisano te techniki bardziej szczegółowo.

Korzystanie z modeli skwantowanych

W tej sekcji wyjaśniono, w jaki sposób delegat GPU przyspiesza 8-bitowe modele kwantyzowane, w tym następujące:

Aby zoptymalizować wydajność, użyj modeli, które mają zarówno zmiennoprzecinkowy tensor wejściowy, jak i wyjściowy.

Jak to działa?

Ponieważ zaplecze GPU obsługuje tylko wykonywanie zmiennoprzecinkowe, uruchamiamy modele skwantowane, dając mu „widok zmiennoprzecinkowy” oryginalnego modelu. Na wysokim poziomie obejmuje to następujące kroki:

  • Stałe tensory (takie jak wagi/odchylenie) są dekwantyzowane po umieszczeniu 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ą skwantowane 8-bitowo, są dekwantyzowane 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 pomiędzy operacjami, aby naśladować zachowanie skwantowane. Takie podejście jest konieczne w przypadku modeli, w których operatorzy oczekują, że aktywacje będą zgodne z granicami poznanymi podczas kwantyzacji.

Informacje na temat włączania tej funkcji za pomocą delegata GPU można znaleźć w następujących sekcjach:

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 zapisanych na dysku z poprzednich uruchomień. Takie podejście pozwala uniknąć ponownej kompilacji i może skrócić czas uruchamiania nawet o 90%. Poprawę tę osiąga 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);
      

Korzystając z funkcji serializacji, upewnij się, że Twój kod jest zgodny z następującymi zasadami implementacji:

  • Przechowuj dane serializacji w katalogu, który nie jest dostępny 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 konkretnego modelu. Można obliczyć token modelu, generując odcisk palca z danych modelu przy użyciu bibliotek takich jak farmhash::Fingerprint64 .