Sterowniki API sieci neuronowych

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Ta strona zawiera omówienie sposobu implementacji sterownika interfejsu API sieci neuronowych (NNAPI). Więcej informacji można znaleźć w dokumentacji znajdującej się w plikach definicji HAL w katalogu hardware/interfaces/neuralnetworks . Przykładowa implementacja sterownika znajduje się w frameworks/ml/nn/driver/sample .

Aby uzyskać więcej informacji na temat interfejsu API sieci neuronowych, zobacz Interfejs API sieci neuronowych .

Sieci neuronowe HAL

Sieci neuronowe (NN) HAL definiuje abstrakcję różnych urządzeń , takich jak procesory graficzne (GPU) i cyfrowe procesory sygnałowe (DSP), które znajdują się w produkcie (na przykład telefonie lub tablecie). Sterowniki dla tych urządzeń muszą być zgodne z NN HAL. Interfejs jest określony w plikach definicji HAL w hardware/interfaces/neuralnetworks .

Ogólny przepływ interfejsu między platformą a sterownikiem przedstawiono na rysunku 1.

Przepływ sieci neuronowych

Rysunek 1. Przebieg sieci neuronowych

Inicjalizacja

Podczas inicjalizacji struktura wysyła zapytanie do sterownika o jego możliwości przy użyciu IDevice::getCapabilities_1_3 . Struktura @1.3::Capabilities zawiera wszystkie typy danych i reprezentuje nierelaksowaną wydajność przy użyciu wektora.

Aby określić, w jaki sposób przydzielić obliczenia do dostępnych urządzeń, struktura wykorzystuje możliwości, aby zrozumieć, jak szybko i jak wydajnie energetycznie każdy sterownik może wykonać wykonanie. Aby dostarczyć te informacje, kierowca musi podać znormalizowane wartości wydajności w oparciu o wykonanie obciążeń referencyjnych.

Aby określić wartości zwracane przez sterownik w odpowiedzi na IDevice::getCapabilities_1_3 , użyj aplikacji porównawczej NNAPI do pomiaru wydajności dla odpowiednich typów danych. Modele MobileNet v1 i v2, asr_float i tts_float są zalecane do pomiaru wydajności dla 32-bitowych wartości zmiennoprzecinkowych, a skwantyzowane modele MobileNet v1 i v2 są zalecane dla 8-bitowych skwantyzowanych wartości. Aby uzyskać więcej informacji, zobacz pakiet testów usługi Android Machine Learning .

W systemie Android 9 i niższych struktura Capabilities zawiera informacje o wydajności sterownika tylko dla tensorów zmiennoprzecinkowych i skwantyzowanych i nie obejmuje skalarnych typów danych.

W ramach procesu inicjowania struktura może wysyłać zapytania o więcej informacji przy użyciu IDevice::getType , IDevice::getVersionString , IDevice:getSupportedExtensions i IDevice::getNumberOfCacheFilesNeeded .

Pomiędzy ponownymi uruchomieniami produktu struktura oczekuje, że wszystkie zapytania opisane w tej sekcji będą zawsze zgłaszać te same wartości dla danego sterownika. W przeciwnym razie aplikacja korzystająca z tego sterownika może wykazywać zmniejszoną wydajność lub nieprawidłowe działanie.

Kompilacja

Struktura określa, których urządzeń użyć, gdy otrzyma żądanie z aplikacji. W Androidzie 10 aplikacje mogą wykrywać i określać urządzenia, z których wybiera platforma. Aby uzyskać więcej informacji, zobacz Wykrywanie i przypisywanie urządzeń .

W czasie kompilacji modelu struktura wysyła model do każdego kandydata na sterownik, wywołując IDevice::getSupportedOperations_1_3 . Każdy sterownik zwraca tablicę wartości logicznych wskazujących, które operacje modelu są obsługiwane. Sterownik może stwierdzić, że nie może obsłużyć danej operacji z wielu powodów. Na przykład:

  • Sterownik nie obsługuje typu danych.
  • Sterownik obsługuje tylko operacje z określonymi parametrami wejściowymi. Na przykład sterownik może obsługiwać operacje splotu 3x3 i 5x5, ale nie 7x7.
  • Sterownik ma ograniczenia pamięci, które uniemożliwiają mu obsługę dużych wykresów lub danych wejściowych.

Podczas kompilacji operandy wejściowe, wyjściowe i wewnętrzne modelu, zgodnie z opisem w OperandLifeTime , mogą mieć nieznane wymiary lub rangę. Aby uzyskać więcej informacji, zobacz Kształt wyjściowy .

Struktura instruuje każdy wybrany sterownik, aby przygotował się do wykonania podzestawu modelu, wywołując IDevice::prepareModel_1_3 . Następnie każdy sterownik kompiluje swój podzbiór. Na przykład kierowca może wygenerować kod lub utworzyć zmienioną kolejność kopii wag. Ponieważ między kompilacją modelu a wykonaniem żądań może upłynąć znaczna ilość czasu, podczas kompilacji nie należy przypisywać zasobów, takich jak duże fragmenty pamięci urządzenia.

W przypadku powodzenia sterownik zwraca uchwyt @1.3::IPreparedModel . Jeśli sterownik zwróci kod błędu podczas przygotowywania swojego podzbioru modelu, struktura uruchomi cały model na procesorze.

Aby skrócić czas kompilacji podczas uruchamiania aplikacji, sterownik może buforować artefakty kompilacji. Aby uzyskać więcej informacji, zobacz Buforowanie kompilacji .

Wykonanie

Gdy aplikacja prosi platformę o wykonanie żądania, struktura domyślnie wywołuje metodę IPreparedModel::executeSynchronously_1_3 HAL w celu wykonania synchronicznego wykonania na przygotowanym modelu. Żądanie może być również wykonywane asynchronicznie przy użyciu metody execute_1_3 , metody executeFenced (zobacz Wykonywanie chronione ) lub wykonywane przy użyciu wykonywania seryjnego .

Synchroniczne wywołania wykonania poprawiają wydajność i zmniejszają obciążenie wątków w porównaniu z wywołaniami asynchronicznymi, ponieważ kontrola jest zwracana do procesu aplikacji dopiero po zakończeniu wykonywania. Oznacza to, że sterownik nie potrzebuje osobnego mechanizmu do powiadamiania procesu aplikacji o zakończeniu wykonywania.

W przypadku asynchronicznej metody execute_1_3 kontrola powraca do procesu aplikacji po rozpoczęciu wykonywania, a sterownik musi powiadomić platformę o zakończeniu wykonywania przy użyciu @1.3::IExecutionCallback .

Parametr Request przekazany do metody execute zawiera listę operandów wejściowych i wyjściowych używanych do wykonania. Pamięć, w której przechowywane są dane operandów, musi wykorzystywać kolejność głównych wierszy, przy czym pierwszy wymiar iteruje najwolniej i nie może zawierać dopełnienia na końcu żadnego wiersza. Aby uzyskać więcej informacji na temat typów operandów, zobacz Operandy .

W przypadku sterowników NN HAL 1.2 lub nowszych po wykonaniu żądania stan błędu, kształt danych wyjściowych i informacje o taktowaniu są zwracane do struktury. Podczas wykonywania operandy wyjściowe lub wewnętrzne modelu mogą mieć jeden lub więcej nieznanych wymiarów lub nieznanej rangi. Gdy co najmniej jeden operand wyjściowy ma nieznany wymiar lub rangę, sterownik musi zwrócić informacje wyjściowe o dynamicznym rozmiarze.

W przypadku sterowników z NN HAL 1.1 lub niższym po zakończeniu żądania zwracany jest tylko stan błędu. Wymiary operandów wejściowych i wyjściowych muszą być w pełni określone, aby wykonanie zakończyło się pomyślnie. Argumenty wewnętrzne mogą mieć jeden lub więcej nieznanych wymiarów, ale muszą mieć określoną rangę.

W przypadku żądań użytkowników, które obejmują wiele sterowników, struktura jest odpowiedzialna za rezerwację pamięci pośredniej i sekwencjonowanie wywołań do każdego sterownika.

Wiele żądań można zainicjować równolegle na tym samym @1.3::IPreparedModel . Sterownik może wykonywać żądania równolegle lub serializować wykonania.

Ramka może poprosić kierowcę o zachowanie więcej niż jednego przygotowanego modelu. Na przykład przygotuj model m1 , przygotuj m2 , wykonaj żądanie r1 na m1 , wykonaj r2 na m2 , wykonaj r3 na m1 , wykonaj r4 na m2 , zwolnij (opisane w Czyszczenie ) m1 i zwolnij m2 .

Aby uniknąć powolnego pierwszego wykonania, które mogłoby spowodować złe wrażenia użytkownika (na przykład zacinanie się pierwszej klatki), sterownik powinien wykonać większość inicjalizacji w fazie kompilacji. Inicjalizacja przy pierwszym uruchomieniu powinna być ograniczona do działań, które mają negatywny wpływ na kondycję systemu, jeśli są wykonywane wcześnie, takich jak rezerwowanie dużych buforów tymczasowych lub zwiększanie częstotliwości zegara urządzenia. Sterowniki, które mogą przygotować tylko ograniczoną liczbę modeli współbieżnych, mogą być zmuszone do inicjalizacji przy pierwszym uruchomieniu.

W systemie Android 10 lub nowszym, w przypadkach, gdy wiele wykonań z tym samym przygotowanym modelem jest wykonywanych w krótkich odstępach czasu, klient może zdecydować się na użycie obiektu serii wykonania do komunikacji między aplikacjami a procesami sterownika. Aby uzyskać więcej informacji, zobacz Wykonywanie serii i Kolejki szybkich komunikatów .

Aby poprawić wydajność wielu wykonań w krótkich odstępach czasu, sterownik może zatrzymać tymczasowe bufory lub zwiększyć częstotliwość taktowania. Zaleca się utworzenie wątku nadzorującego w celu zwolnienia zasobów, jeśli po określonym czasie nie zostaną utworzone żadne nowe żądania.

Kształt wyjściowy

W przypadku żądań, w których jeden lub więcej operandów wyjściowych nie ma określonych wszystkich wymiarów, sterownik musi dostarczyć listę kształtów wyjściowych zawierającą informacje o wymiarach dla każdego operandu wyjściowego po wykonaniu. Aby uzyskać więcej informacji na temat wymiarów, zobacz OutputShape .

Jeśli wykonanie nie powiedzie się z powodu zbyt małego bufora wyjściowego, sterownik musi wskazać, które operandy wyjściowe mają niewystarczający rozmiar bufora na liście kształtów wyjściowych i powinien zgłosić jak najwięcej informacji o wymiarach, używając zera dla wymiarów, które są nieznane.

wyczucie czasu

W systemie Android 10 aplikacja może zapytać o czas wykonania, jeśli określiła jedno urządzenie do użycia podczas procesu kompilacji. Aby uzyskać szczegółowe informacje, zobacz MeasureTiming oraz Wykrywanie i przypisywanie urządzeń . W takim przypadku sterownik NN HAL 1.2 musi mierzyć czas trwania wykonania lub zgłaszać UINT64_MAX (aby wskazać, że czas trwania jest niedostępny) podczas wykonywania żądania. Kierowca powinien zminimalizować wszelkie straty wydajności wynikające z pomiaru czasu wykonania.

Sterownik zgłasza następujące czasy trwania w mikrosekundach w strukturze Timing :

  • Czas wykonania na urządzeniu: nie obejmuje czasu wykonania w sterowniku, który działa na procesorze hosta.
  • Czas wykonania w sterowniku: Obejmuje czas wykonania na urządzeniu.

Te czasy trwania muszą obejmować czas, w którym wykonanie jest zawieszone, na przykład, gdy wykonanie zostało wywłaszczone przez inne zadania lub gdy oczekuje na udostępnienie zasobu.

Gdy sterownik nie został poproszony o zmierzenie czasu trwania wykonania lub wystąpił błąd wykonania, sterownik musi zgłaszać czasy trwania jako UINT64_MAX . Nawet jeśli sterownik został poproszony o zmierzenie czasu trwania wykonania, może zamiast tego zgłosić UINT64_MAX dla czasu na urządzeniu, czasu w sterowniku lub obu. Gdy sterownik zgłasza oba czasy trwania jako wartość inną niż UINT64_MAX , czas wykonania w sterowniku musi być równy lub przekraczać czas na urządzeniu.

Ogrodzona egzekucja

W Androidzie 11 NNAPI pozwala egzekucjom czekać na listę uchwytów sync_fence i opcjonalnie zwracać obiekt sync_fence , który jest sygnalizowany po zakończeniu wykonywania. Zmniejsza to obciążenie w przypadku małych modeli sekwencji i przypadków użycia przesyłania strumieniowego. Wykonywanie chronione pozwala również na wydajniejsze współdziałanie z innymi składnikami, które mogą sygnalizować lub czekać na sync_fence . Aby uzyskać więcej informacji na temat sync_fence , zobacz Struktura synchronizacji .

W wykonywaniu chronionym struktura wywołuje metodę IPreparedModel::executeFenced w celu uruchomienia zabezpieczonego, asynchronicznego wykonywania na przygotowanym modelu z wektorem ogrodzeń synchronizacji, na które należy czekać. Jeśli zadanie asynchroniczne zostanie zakończone przed zwróceniem wywołania, można zwrócić puste dojście dla sync_fence . Należy również zwrócić obiekt IFencedExecutionCallback , aby umożliwić platformie zapytanie o stan błędu i informacje o czasie trwania.

Po zakończeniu wykonywania następujące dwie wartości chronometrażu mierzące czas trwania wykonania można zapytać za pomocą IFencedExecutionCallback::getExecutionInfo .

  • timingLaunched : Czas trwania od momentu executeFenced do momentu, gdy executeFenced zasygnalizuje zwrócenie syncFence .
  • timingFenced : Czas od momentu, w którym wszystkie ogrodzenia synchronizacji, na które czeka wykonanie, zostaną zasygnalizowane, gdy executeFenced zasygnalizuje zwrócony syncFence .

Kontrola przepływu

W przypadku urządzeń z systemem Android 11 lub nowszym NNAPI obejmuje dwie operacje przepływu sterowania, IF i WHILE , które przyjmują inne modele jako argumenty i wykonują je warunkowo ( IF ) lub wielokrotnie ( WHILE ). Aby uzyskać więcej informacji o tym, jak to zaimplementować, zobacz Przepływ sterowania .

Jakość usługi

W Androidzie 11 NNAPI obejmuje ulepszoną jakość usług (QoS), umożliwiając aplikacji wskazanie względnych priorytetów jej modeli, maksymalnego czasu oczekiwanego na przygotowanie modelu oraz maksymalnego czasu oczekiwanego na wykonanie do ukończenia. Aby uzyskać więcej informacji, zobacz Jakość usług .

Sprzątać

Gdy aplikacja zostanie zakończona przy użyciu przygotowanego modelu, struktura zwalnia odwołanie do @1.3::IPreparedModel obiektu. Gdy obiekt IPreparedModel nie jest już przywoływany, jest automatycznie niszczony w usłudze sterownika, która go utworzyła. Zasoby specyficzne dla modelu można odzyskać w tym momencie w implementacji destruktora przez sterownik. Jeśli usługa sterownika chce, aby obiekt IPreparedModel był automatycznie niszczony, gdy nie jest już potrzebny klientowi, nie może przechowywać żadnych odwołań do obiektu IPreparedModel po IPreparedeModel obiektu IPreparedeModel przez IPreparedModelCallback::notify_1_3 .

użycie procesora

Oczekuje się, że sterowniki będą używać procesora do konfigurowania obliczeń. Sterowniki nie powinny używać procesora do wykonywania obliczeń wykresów, ponieważ zakłóca to zdolność struktury do prawidłowego przydzielania pracy. Sterownik powinien zgłosić części, których nie może obsłużyć, do struktury i pozwolić ramowi zająć się resztą.

Struktura zapewnia implementację procesora dla wszystkich operacji NNAPI z wyjątkiem operacji zdefiniowanych przez dostawcę. Aby uzyskać więcej informacji, zobacz Rozszerzenia dostawców .

Operacje wprowadzone w Androidzie 10 (API poziom 29) mają jedynie referencyjną implementację CPU do weryfikacji poprawności testów CTS i VTS. Zoptymalizowane implementacje zawarte w ramach mobilnego uczenia maszynowego są preferowane w stosunku do implementacji procesora NNAPI.

Funkcje użytkowe

Baza kodów NNAPI zawiera funkcje użytkowe, z których mogą korzystać usługi kierowców.

Plik frameworks/ml/nn/common/include/Utils.h zawiera różne funkcje narzędziowe, takie jak te używane do rejestrowania i konwertowania między różnymi wersjami NN HAL.

  • VLogging: VLOG to makro otaczające LOG Androida, które rejestruje komunikat tylko wtedy, gdy we właściwości debug.nn.vlog jest ustawiony odpowiedni tag. initVLogMask() musi zostać wywołana przed wywołaniem VLOG . VLOG_IS_ON można użyć do sprawdzenia, czy VLOG jest aktualnie włączony, umożliwiając pominięcie skomplikowanego kodu rejestrowania, jeśli nie jest potrzebny. Wartość nieruchomości musi być jedną z następujących:

    • Pusty ciąg znaków wskazujący, że nie ma być wykonywane żadne rejestrowanie.
    • Token 1 lub all , wskazujący, że należy wykonać całe logowanie.
    • Lista znaczników rozdzielona spacjami, przecinkami lub dwukropkami, wskazująca, które rejestrowanie ma zostać wykonane. Tagi to compilation , cpuexe , driver , execution , manager i model .
  • compliantWithV1_* : Zwraca wartość true , jeśli obiekt NN HAL można przekonwertować na ten sam typ innej wersji HAL bez utraty informacji. Na przykład wywołanie compliantWithV1_0 na V1_2::Model zwraca wartość false , jeśli model zawiera typy operacji wprowadzone w NN HAL 1,1 lub NN HAL 1,2.

  • convertToV1_* : Konwertuje obiekt NN HAL z jednej wersji na inną. Ostrzeżenie jest rejestrowane, jeśli konwersja powoduje utratę informacji (to znaczy, jeśli nowa wersja typu nie może w pełni reprezentować wartości).

  • Możliwości: Funkcje nonExtensionOperandPerformance i update mogą być używane do tworzenia pola Capabilities::operandPerformance .

  • Zapytanie dotyczące właściwości typów: isExtensionOperandType , isExtensionOperationType , nonExtensionSizeOfData , nonExtensionOperandSizeOfData , nonExtensionOperandTypeIsScalar , tensorHasUnspecifiedDimensions .

Plik frameworks/ml/nn/common/include/ValidateHal.h zawiera funkcje narzędziowe do sprawdzania poprawności obiektu NN HAL zgodnie ze specyfikacją jego wersji HAL.

  • validate* : Zwraca wartość true , jeśli obiekt NN HAL jest ważny zgodnie ze specyfikacją jego wersji HAL. Typy OEM i typy rozszerzeń nie są sprawdzane. Na przykład validateModel zwraca wartość false , jeśli model zawiera operację odwołującą się do nieistniejącego indeksu operandu lub operację, która nie jest obsługiwana w tej wersji warstwy HAL.

Plik frameworks/ml/nn/common/include/Tracing.h zawiera makra upraszczające dodawanie informacji systracing do kodu sieci neuronowych. Przykład można znaleźć w wywołaniach makr NNTRACE_* w przykładowym sterowniku .

Plik frameworks/ml/nn/common/include/GraphDump.h zawiera funkcję narzędzia do zrzutu zawartości Model w formie graficznej do celów debugowania.

  • graphDump : Zapisuje reprezentację modelu w formacie Graphviz ( .dot ) do określonego strumienia (jeśli został podany) lub do logcata (jeśli nie podano strumienia).

Walidacja

Aby przetestować implementację NNAPI, użyj testów VTS i CTS zawartych w środowisku Android. VTS sprawdza Twoich kierowców bezpośrednio (bez użycia frameworka), podczas gdy CTS ćwiczy ich pośrednio poprzez framework. Testują one każdą metodę API i sprawdzają, czy wszystkie operacje obsługiwane przez sterowniki działają poprawnie i dostarczają wyniki spełniające wymagania dotyczące precyzji.

Wymagania dotyczące precyzji w CTS i VTS dla NNAPI są następujące:

  • Zmiennoprzecinkowy: abs(oczekiwany - rzeczywisty) <= atol + rtol * abs(oczekiwany); gdzie:

    • Dla fp32, atol = 1e-5f, rtol = 5,0f * 1,1920928955078125e-7
    • Dla fp16 atol = rtol = 5.0f * 0.0009765625f
  • Kwantyzacja : różnica o jeden (z wyjątkiem mobilenet_quantized , która jest różnicą o trzy)

  • Wartość logiczna: dokładne dopasowanie

Jednym ze sposobów testowania NNAPI przez CTS jest generowanie ustalonych wykresów pseudolosowych używanych do testowania i porównywania wyników wykonania każdego sterownika z implementacją referencyjną NNAPI. W przypadku sterowników z NN HAL 1.2 lub nowszym, jeśli wyniki nie spełniają kryteriów precyzji, CTS zgłasza błąd i zrzuca plik specyfikacji dla uszkodzonego modelu w katalogu /data/local/tmp w celu debugowania. Aby uzyskać więcej informacji na temat kryteriów precyzji, zobacz TestRandomGraph.cpp i TestHarness.h .

Testowanie rozmycia

Celem testów rozmytych jest znalezienie awarii, stwierdzeń, naruszeń pamięci lub ogólnego niezdefiniowanego zachowania w testowanym kodzie z powodu czynników, takich jak nieoczekiwane dane wejściowe. Do testowania rozmytego NNAPI system Android używa testów opartych na libFuzzer , które są wydajne w rozmywaniu, ponieważ wykorzystują pokrycie linii z poprzednich przypadków testowych do generowania nowych losowych danych wejściowych. Na przykład libFuzzer faworyzuje przypadki testowe, które działają na nowych liniach kodu. To znacznie skraca czas potrzebny na znalezienie problematycznego kodu podczas testów.

Aby przeprowadzić testy rozmyte w celu zweryfikowania implementacji sterownika, zmodyfikuj frameworks/ml/nn/runtime/test/android_fuzzing/DriverFuzzTest.cpp w narzędziu testowym libneuralnetworks_driver_fuzzer znajdującym się w AOSP, aby uwzględnić kod sterownika. Aby uzyskać więcej informacji na temat testowania fuzz NNAPI, zobacz frameworks/ml/nn/runtime/test/android_fuzzing/README.md .

Bezpieczeństwo

Ponieważ procesy aplikacji komunikują się bezpośrednio z procesem kierowcy, kierowcy muszą weryfikować argumenty odbieranych połączeń. Ta walidacja jest weryfikowana przez VTS. Kod weryfikacyjny znajduje się w frameworks/ml/nn/common/include/ValidateHal.h .

Kierowcy powinni również upewnić się, że aplikacje nie mogą kolidować z innymi aplikacjami podczas korzystania z tego samego urządzenia.

Pakiet testowy uczenia maszynowego na Androida

Android Machine Learning Test Suite (MLTS) to test porównawczy NNAPI zawarty w CTS i VTS do sprawdzania poprawności rzeczywistych modeli na urządzeniach dostawców. Benchmark ocenia opóźnienie i dokładność oraz porównuje wyniki sterowników z wynikami przy użyciu TF Lite działającego na procesorze, dla tego samego modelu i zestawów danych. Gwarantuje to, że dokładność sterownika nie jest gorsza niż implementacja referencyjna procesora.

Twórcy platformy Android również używają MLTS do oceny opóźnienia i dokładności sterowników.

Benchmark NNAPI można znaleźć w dwóch projektach w AOSP:

Modele i zbiory danych

Test porównawczy NNAPI wykorzystuje następujące modele i zestawy danych.

  • MobileNetV1 float i u8 skwantyzowane w różnych rozmiarach, działają na małym podzbiorze (1500 obrazów) Open Images Dataset v4.
  • MobileNetV2 float i u8 skwantyzowane w różnych rozmiarach, działają na małym podzbiorze (1500 obrazów) Open Images Dataset v4.
  • Model akustyczny oparty na pamięci długoterminowej (LSTM) dla zamiany tekstu na mowę, uruchomiony na małym podzbiorze zestawu CMU Arctic.
  • Model akustyczny oparty na LSTM do automatycznego rozpoznawania mowy, uruchamiany na niewielkim podzbiorze zbioru danych LibriSpeech.

Aby uzyskać więcej informacji, zobacz platform/test/mlts/models .

Test naprężeń

Pakiet testowy usługi Android Machine Learning obejmuje serię testów zderzeniowych w celu sprawdzenia odporności sterowników w warunkach intensywnego użytkowania lub w skrajnych przypadkach zachowań klientów.

Wszystkie testy zderzeniowe zapewniają następujące funkcje:

  • Wykrywanie zawieszenia: jeśli klient NNAPI zawiesi się podczas testu, test kończy się niepowodzeniem z przyczyną niepowodzenia HANG , a zestaw testów przechodzi do następnego testu.
  • Wykrywanie awarii klienta NNAPI: testy przetrwają awarie klienta, a testy kończą się niepowodzeniem z przyczyną niepowodzenia CRASH .
  • Wykrywanie awarii sterownika: testy mogą wykryć awarię sterownika, która powoduje awarię wywołania NNAPI. Należy pamiętać, że mogą wystąpić awarie procesów sterownika, które nie powodują awarii NNAPI i nie powodują niepowodzenia testu. Aby pokryć tego rodzaju awarię, zaleca się uruchomienie polecenia tail w dzienniku systemowym w przypadku błędów lub awarii związanych ze sterownikami.
  • Kierowanie na wszystkie dostępne akceleratory: testy są przeprowadzane na wszystkich dostępnych sterownikach.

Wszystkie testy zderzeniowe mają następujące cztery możliwe wyniki:

  • SUCCESS : Wykonanie zakończone bez błędu.
  • FAILURE : Wykonanie nie powiodło się. Zazwyczaj spowodowane niepowodzeniem podczas testowania modelu, wskazujące, że sterownik nie mógł skompilować lub wykonać modelu.
  • HANG : Proces testowy przestał odpowiadać.
  • CRASH : Proces testowy uległ awarii.

Aby uzyskać więcej informacji na temat testów warunków skrajnych i pełną listę testów zderzeniowych, zobacz platform/test/mlts/benchmark/README.txt .

Korzystanie z MLTS

Aby użyć MLTS:

  1. Podłącz urządzenie docelowe do swojej stacji roboczej i upewnij się, że jest osiągalne przez adb . Wyeksportuj zmienną środowiskową ANDROID_SERIAL urządzenia docelowego, jeśli podłączonych jest więcej niż jedno urządzenie.
  2. cd do katalogu źródłowego najwyższego poziomu systemu Android.

    source build/envsetup.sh
    lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available.
    ./test/mlts/benchmark/build_and_run_benchmark.sh
    

    Na koniec testu porównawczego wyniki są prezentowane jako strona HTML i przekazywane do xdg-open .

Aby uzyskać więcej informacji, zobacz platform/test/mlts/benchmark/README.txt .

Wersje HAL sieci neuronowych

W tej sekcji opisano zmiany wprowadzone w wersjach Android i Neural Networks HAL.

Androida 11

Android 11 wprowadza NN HAL 1.3, który zawiera następujące znaczące zmiany.

  • Obsługa podpisanej 8-bitowej kwantyzacji w NNAPI. Dodaje typ operandu TENSOR_QUANT8_ASYMM_SIGNED . Sterowniki z NN HAL 1.3 obsługujące operacje z kwantyzacją bez znaku muszą również obsługiwać podpisane warianty tych operacji. Podczas uruchamiania wersji ze znakiem i bez znaku większości operacji skwantyzowanych sterowniki muszą dawać takie same wyniki do przesunięcia 128. Istnieje pięć wyjątków od tego wymagania: CAST , HASHTABLE_LOOKUP , LSH_PROJECTION , PAD_V2 i QUANTIZED_16BIT_LSTM . Operacja QUANTIZED_16BIT_LSTM nie obsługuje operandów ze znakiem, a pozostałe cztery operacje obsługują kwantyzację ze znakiem, ale nie wymagają, aby wyniki były takie same.
  • Obsługa ogrodzonych wykonań, w których struktura wywołuje metodę IPreparedModel::executeFenced w celu uruchomienia ogrodzonego, asynchronicznego wykonania na przygotowanym modelu z wektorem ogrodzeń synchronizacji, na które należy czekać. Aby uzyskać więcej informacji, zobacz Wykonywanie zabezpieczone .
  • Wsparcie dla przepływu sterowania. Dodaje operacje IF i WHILE , które przyjmują inne modele jako argumenty i wykonują je warunkowo ( IF ) lub wielokrotnie ( WHILE ). Aby uzyskać więcej informacji, zobacz Przepływ sterowania .
  • Poprawiona jakość usług (QoS), ponieważ aplikacje mogą wskazywać względne priorytety swoich modeli, maksymalny oczekiwany czas na przygotowanie modelu oraz maksymalny oczekiwany czas na ukończenie wykonania. Aby uzyskać więcej informacji, zobacz Jakość usług .
  • Obsługa domen pamięci, które zapewniają interfejsy alokatorów dla buforów zarządzanych przez sterowniki. Pozwala to na przekazywanie natywnych pamięci urządzenia między wykonaniami, eliminując niepotrzebne kopiowanie danych i transformację między kolejnymi wykonaniami na tym samym sterowniku. Aby uzyskać więcej informacji, zobacz Domeny pamięci .

Androida 10

Android 10 wprowadza NN HAL 1.2, który zawiera następujące znaczące zmiany.

  • Struktura Capabilities obejmuje wszystkie typy danych, w tym typy danych skalarnych, i reprezentuje niezrelaksowaną wydajność przy użyciu wektora, a nie nazwanych pól.
  • Metody getVersionString i getType umożliwiają platformie pobieranie informacji o typie urządzenia ( DeviceType ) i wersji. Zobacz Wykrywanie i przypisywanie urządzeń .
  • Metoda executeSynchronously jest wywoływana domyślnie w celu synchronicznego wykonywania wykonania. Metoda execute_1_2 mówi platformie, aby wykonała wykonanie asynchronicznie. Zobacz Wykonanie .
  • Parametr MeasureTiming do executeSynchronously , execute_1_2 i seryjne wykonanie określa, czy sterownik ma mierzyć czas trwania wykonania. Wyniki są raportowane w strukturze Timing . Zobacz Timing .
  • Obsługa wykonań, w których jeden lub więcej operandów wyjściowych ma nieznany wymiar lub rangę. Zobacz Kształt wyjściowy .
  • Obsługa rozszerzeń dostawcy, które są zbiorami operacji i typów danych zdefiniowanych przez dostawcę. Sterownik zgłasza obsługiwane rozszerzenia za pomocą metody IDevice::getSupportedExtensions . Zobacz Rozszerzenia dostawcy .
  • Zdolność obiektu burst do kontrolowania zestawu wykonań burst przy użyciu szybkich kolejek komunikatów (FMQ) do komunikacji między aplikacjami a procesami sterownika, zmniejszając opóźnienia. Zobacz Wykonywanie serii i kolejki szybkich komunikatów .
  • Wsparcie dla AHardwareBuffer, aby umożliwić sterownikowi wykonywanie wykonań bez kopiowania danych. Zobacz AHardwareBuffer .
  • Ulepszona obsługa buforowania artefaktów kompilacji w celu skrócenia czasu kompilacji podczas uruchamiania aplikacji. Zobacz Buforowanie kompilacji .

Android 10 wprowadza następujące typy operandów i operacje.

  • Typy operandów

    • ANEURALNETWORKS_BOOL
    • ANEURALNETWORKS_FLOAT16
    • ANEURALNETWORKS_TENSOR_BOOL8
    • ANEURALNETWORKS_TENSOR_FLOAT16
    • ANEURALNETWORKS_TENSOR_QUANT16_ASYMM
    • ANEURALNETWORKS_TENSOR_QUANT16_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL
  • Operacje

    • ANEURALNETWORKS_ABS
    • ANEURALNETWORKS_ARGMAX
    • ANEURALNETWORKS_ARGMIN
    • ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN
    • ANEURALNETWORKS_BOX_WITH_NMS_LIMIT
    • ANEURALNETWORKS_CAST
    • ANEURALNETWORKS_CHANNEL_SHUFFLE
    • ANEURALNETWORKS_DETECTION_POSTPROCESSING
    • ANEURALNETWORKS_EQUAL
    • ANEURALNETWORKS_EXP
    • ANEURALNETWORKS_EXPAND_DIMS
    • ANEURALNETWORKS_GATHER
    • ANEURALNETWORKS_GENERATE_PROPOSALS
    • ANEURALNETWORKS_GREATER
    • ANEURALNETWORKS_GREATER_EQUAL
    • ANEURALNETWORKS_GROUPED_CONV_2D
    • ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT
    • ANEURALNETWORKS_INSTANCE_NORMALIZATION
    • ANEURALNETWORKS_LESS
    • ANEURALNETWORKS_LESS_EQUAL
    • ANEURALNETWORKS_LOG
    • ANEURALNETWORKS_LOGICAL_AND
    • ANEURALNETWORKS_LOGICAL_NOT
    • ANEURALNETWORKS_LOGICAL_OR
    • ANEURALNETWORKS_LOG_SOFTMAX
    • ANEURALNETWORKS_MAXIMUM
    • ANEURALNETWORKS_MINIMUM
    • ANEURALNETWORKS_NEG
    • ANEURALNETWORKS_NOT_EQUAL
    • ANEURALNETWORKS_PAD_V2
    • ANEURALNETWORKS_POW
    • ANEURALNETWORKS_PRELU
    • ANEURALNETWORKS_QUANTIZE
    • ANEURALNETWORKS_QUANTIZED_16BIT_LSTM
    • ANEURALNETWORKS_RANDOM_MULTINOMIAL
    • ANEURALNETWORKS_REDUCE_ALL
    • ANEURALNETWORKS_REDUCE_ANY
    • ANEURALNETWORKS_REDUCE_MAX
    • ANEURALNETWORKS_REDUCE_MIN
    • ANEURALNETWORKS_REDUCE_PROD
    • ANEURALNETWORKS_REDUCE_SUM
    • ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR
    • ANEURALNETWORKS_ROI_ALIGN
    • ANEURALNETWORKS_ROI_POOLING
    • ANEURALNETWORKS_RSQRT
    • ANEURALNETWORKS_SELECT
    • ANEURALNETWORKS_SIN
    • ANEURALNETWORKS_SLICE
    • ANEURALNETWORKS_SPLIT
    • ANEURALNETWORKS_SQRT
    • ANEURALNETWORKS_TILE
    • ANEURALNETWORKS_TOPK_V2
    • ANEURALNETWORKS_TRANSPOSE_CONV_2D
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN

Android 10 wprowadza aktualizacje do wielu dotychczasowych operacji. Aktualizacje dotyczą głównie:

  • Obsługa układu pamięci NCHW
  • Obsługa tensorów o randze innej niż 4 w operacjach softmax i normalizacji
  • Obsługa rozszerzonych splotów
  • Obsługa wejść z mieszaną kwantyzacją w ANEURALNETWORKS_CONCATENATION

Poniższa lista przedstawia operacje zmodyfikowane w systemie Android 10. Aby uzyskać szczegółowe informacje o zmianach, zobacz OperationCode w dokumentacji referencyjnej NNAPI.

  • ANEURALNETWORKS_ADD
  • ANEURALNETWORKS_AVERAGE_POOL_2D
  • ANEURALNETWORKS_BATCH_TO_SPACE_ND
  • ANEURALNETWORKS_CONCATENATION
  • ANEURALNETWORKS_CONV_2D
  • ANEURALNETWORKS_DEPTHWISE_CONV_2D
  • ANEURALNETWORKS_DEPTH_TO_SPACE
  • ANEURALNETWORKS_DEQUANTIZE
  • ANEURALNETWORKS_DIV
  • ANEURALNETWORKS_FLOOR
  • ANEURALNETWORKS_FULLY_CONNECTED
  • ANEURALNETWORKS_L2_NORMALIZATION
  • ANEURALNETWORKS_L2_POOL_2D
  • ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION
  • ANEURALNETWORKS_LOGISTIC
  • ANEURALNETWORKS_LSH_PROJECTION
  • ANEURALNETWORKS_LSTM
  • ANEURALNETWORKS_MAX_POOL_2D
  • ANEURALNETWORKS_MEAN
  • ANEURALNETWORKS_MUL
  • ANEURALNETWORKS_PAD
  • ANEURALNETWORKS_RELU
  • ANEURALNETWORKS_RELU1
  • ANEURALNETWORKS_RELU6
  • ANEURALNETWORKS_RESHAPE
  • ANEURALNETWORKS_RESIZE_BILINEAR
  • ANEURALNETWORKS_RNN
  • ANEURALNETWORKS_ROI_ALIGN
  • ANEURALNETWORKS_SOFTMAX
  • ANEURALNETWORKS_SPACE_TO_BATCH_ND
  • ANEURALNETWORKS_SPACE_TO_DEPTH
  • ANEURALNETWORKS_SQUEEZE
  • ANEURALNETWORKS_STRIDED_SLICE
  • ANEURALNETWORKS_SUB
  • ANEURALNETWORKS_SVDF
  • ANEURALNETWORKS_TANH
  • ANEURALNETWORKS_TRANSPOSE

Androida 9

NN HAL 1.1 został wprowadzony w systemie Android 9 i zawiera następujące znaczące zmiany.

  • IDevice::prepareModel_1_1 zawiera parametr ExecutionPreference . Kierowca może to wykorzystać do dostosowania swojego przygotowania, wiedząc, że aplikacja woli oszczędzać baterię lub będzie wykonywać model w szybkich, następujących po sobie wywołaniach.
  • Dodano dziewięć nowych operacji: BATCH_TO_SPACE_ND , DIV , MEAN , PAD , SPACE_TO_BATCH_ND , SQUEEZE , STRIDED_SLICE , SUB , TRANSPOSE .
  • Aplikacja może określić, że 32-bitowe obliczenia zmiennoprzecinkowe mogą być uruchamiane przy użyciu 16-bitowego zakresu zmiennoprzecinkowego i/lub precyzji przez ustawienie Model.relaxComputationFloat32toFloat16 na true . Struktura Capabilities ma dodatkowe pole relaxedFloat32toFloat16Performance , dzięki czemu kierowca może zgłosić swoje zrelaksowane działanie do struktury.

Androida 8.1

Początkowa warstwa HAL sieci neuronowych (1.0) została wydana w systemie Android 8.1. Aby uzyskać więcej informacji, zobacz /neuralnetworks/1.0/ .