Weź udział w sympozjum Women in ML 7 grudnia Zarejestruj się teraz

Delegaci GPU dla TensorFlow Lite

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:

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:

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:

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 .