Przedstawiciele GPU w usłudze LiteRT

Korzystanie z procesorów graficznych (GPU) do uruchamiania modeli systemów uczących się może znacząco poprawić wydajność modelu i wygodę użytkowników Twoich aplikacji obsługujących ML. LiteRT umożliwia korzystanie z GPU lub inne specjalistyczne procesory za pomocą sterownika sprzętowego o nazwie delegatów. Włączanie korzystania z GPU w LiteRT ML mogą przynieść następujące korzyści:

  • Szybkość – GPU są tworzone z myślą o wysokości przepustowości zadań. Dzięki tej konstrukcji dobrze nadają się do działania głębokich sieci neuronowych, składają się z ogromnej liczby operatorów, z których każdy działa na tensorach wejściowych, mogą być przetwarzane równolegle, co zwykle skraca czas oczekiwania. W w najlepszym scenariuszu uruchamianie modelu przy użyciu GPU może działać wystarczająco szybko, z aplikacjami w czasie rzeczywistym, które wcześniej nie były możliwe.
  • Oszczędność energii – układy GPU bardzo wydajnie wykonują obliczenia związane z systemami uczącymi się. i zoptymalizowany sposób, zużywając zwykle mniej energii niż to samo zadanie uruchomione na procesorach.

Ten dokument zawiera omówienie obsługiwanych GPU w LiteRT, a także do zaawansowanych zastosowań procesorów GPU. Aby uzyskać bardziej szczegółowe informacje o implementacji obsługi GPU na konkretnych platformach, zapoznaj się z tymi przewodnikami:

Obsługa operacji GPU ML

Istnieją pewne ograniczenia co do tego, jakie operacje (operacje TensorFlow ML) mogą być akceptacja przez delegata GPU LiteRT. Przedstawiciel 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łączanie funkcji kwantyzacji support włącza odpowiednie wersje, np. ADD wersja 2.

Rozwiązywanie problemów z obsługą GPU

Jeśli niektóre operacje nie są obsługiwane przez przedstawiciela GPU, platforma tylko część wykresu jest uruchamiana w układzie GPU, a pozostała na procesorze CPU. Termin przy wysokim koszcie synchronizacji CPU/GPU, tryb podzielonego wykonywania często powoduje wolniejsze działanie niż przy korzystaniu z całej sieci samego procesora. 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 problem. niepowodzenie podczas uruchamiania. Gdy testujesz wykonanie modelu z użyciem delegowanego GPU, należy zachować ostrożność w przypadku tych ostrzeżeń. Duża liczba tych ostrzeżeń może wskazują, że Twój model nie najlepiej nadaje się do akceleracji GPU; może wymagać refaktoryzacji modelu.

Przykładowe modele

Poniższe przykładowe modele zostały utworzone z myślą o wykorzystaniu przyspieszenia GPU za pomocą funkcji LiteRT i są przeznaczone do celów referencyjnych i testowania:

Optymalizacja pod kątem GPU

Opisane poniżej techniki mogą pomóc Ci uzyskać większą wydajność podczas uruchamiania modeli na sprzęcie GPU z wykorzystaniem delegacji GPU LiteRT:

  • Operacje zmiany kształtu – niektóre operacje, które są szybkie na procesorze, mogą mieć koszt GPU w urządzeniach mobilnych jest wysoki. Operacje zmiany kształtu są szczególnie ważne drogie – w tym BATCH_TO_SPACE, SPACE_TO_BATCH, SPACE_TO_DEPTH itd. Uważnie przyjrzyj się możliwości zmiany kształtu operacji i wziąć pod uwagę, że mogły one zostać zastosowane wyłącznie do badania danych lub wczesnych iteracji modelu. Usunięcie ich może znacznie poprawić wydajność.

  • Kanały danych obrazów – w GPU dane tensora są dzielone na 4 kanały. a obliczenia na tensorach o kształcie [B,H,W,5] liczą się względem taki sam na tensorze kształtu [B,H,W,8], ale znacznie gorszy niż [B,H,W,4]. Jeśli używany aparat obsługuje ramki obrazu 4-kanałowe wprowadzanie danych RGBA jest znacznie szybsze, skopiować z pamięci 3-kanałowe RGB na 4-kanałowe RGBX.

  • Modele zoptymalizowane pod kątem urządzeń mobilnych – aby uzyskać najlepszą skuteczność, ponowne trenowanie klasyfikatora za pomocą architektury sieci zoptymalizowanej pod kątem urządzeń mobilnych. Optymalizacja pod kątem wnioskowania na urządzeniu może znacznie skrócić czas oczekiwania oraz zużycie energii przez wykorzystanie funkcji sprzętu mobilnego.

Zaawansowana obsługa GPU

Możesz użyć dodatkowych, zaawansowanych technik przetwarzania GPU, aby zapewnić równomierne lepszą wydajność modeli, w tym kwantyzacji i serializacji. W sekcjach poniżej szczegółowo opisujemy te metody.

Korzystanie z modeli kwantowych

W tej sekcji wyjaśniamy, jak delegowany GPU przyspiesza przyspieszenie 8-bitowych kwantyzowanych modeli w tym:

Aby zoptymalizować skuteczność, używaj modeli zawierających zarówno zmiennoprzecinkowe dane wejściowe, tensory wyjściowe.

Jak to działa?

Backend GPU obsługuje tylko wykonywanie zmiennoprzecinkowe, dlatego przeprowadzamy przez nadanie mu widoku zmiennoprzecinkowego oryginalnego modelu. Na zasadniczo, obejmuje to te czynności:

  • Tensory stałe (np. wagi/odchylenia) są dekwantyzowane raz do Pamięć GPU. Ta operacja ma miejsce, gdy osoba przekazująca dostęp jest włączona dla: LiteRT.

  • Dane wejściowe i wyjściowe do programu GPU, jeśli są poddane kwantyzacji 8-bitowej, są zdekwantyzowana i skwantyzowana (odpowiednio) dla każdego wnioskowania. Ta operacja jest przeprowadzana na CPU z wykorzystaniem jąder zoptymalizowanych przez LiteRT.

  • Symulatory kwantyzacji są umieszczane między operacjami, aby naśladować kwantyzację zachowanie użytkownika. To podejście jest konieczne w przypadku modeli, w których operatorzy oczekują aktywacji aby śledzić granice ustalone podczas kwantyzacji.

Informacje o włączaniu tej funkcji z wykorzystaniem przedstawiciela GPU znajdziesz w :

Skrócenie czasu inicjowania za pomocą serializacji

Funkcja przekazywania dostępu do GPU umożliwia wczytywanie ze wstępnie skompilowanego kodu jądra dane modelu są zserializowane i zapisane na dysku z poprzednich uruchomień. Ta metoda pozwala uniknąć i może skrócić czas uruchamiania nawet o 90%. To ulepszenie co można osiągnąć dzięki wymianie miejsca na dysku w celu zaoszczędzenia czasu. Możesz włączyć tę funkcję z kilkoma opcjami konfiguracji, jak pokazano 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);
      

Podczas korzystania z funkcji serializacji Twój kod powinien być zgodny z tymi reguły implementacji:

  • Przechowuj dane serializacji w katalogu, który nie jest dostępny dla innych aplikacji. Na urządzeniach z Androidem użyj funkcji getCodeCacheDir() wskazujący lokalizację prywatną dla bieżącej aplikacji.
  • Token modelu musi być unikalny dla urządzenia w przypadku danego modelu. Dostępne opcje obliczyć token modelu, generując odcisk cyfrowy z danych modelu za pomocą biblioteki, takie jak farmhash::Fingerprint64
.