Ta strona zawiera omówienie implementacji interfejsu Neural Networks API (NNAPI). Więcej informacji znajdziesz w dokumentacji znajdującej się w plikach definicji HAL w hardware/interfaces/neuralnetworks
.
Przykładową implementację sterownika znajdziesz w frameworks/ml/nn/driver/sample
.
Więcej informacji o interfejsie Neural Networks API znajdziesz na stronie Neural Networks API.
Sieci neuronowe HAL
Interfejs HAL dla sieci neuronowych (NN) definiuje abstrakcję różnych urządzeń, takich jak jednostki przetwarzania graficznego (GPU) i procesory sygnałowe (DSP), które są częścią produktu (np. telefonu lub tabletu). Sterowniki tych urządzeń muszą być zgodne z interfejsem NN HAL. Interfejs jest określony w plikach definicji HAL w hardware/interfaces/neuralnetworks
.
Ogólny przepływ danych między interfejsem a sterownikami przedstawia rysunek 1.
Rysunek 1. Przepływ sieci neuronowych
Inicjowanie
Podczas inicjowania platforma wysyła zapytanie do sterownika za pomocą narzędzia IDevice::getCapabilities_1_3
.
Struktura @1.3::Capabilities
obejmuje wszystkie typy danych i reprezentuje niezrelaksowaną wydajność za pomocą wektora.
Aby określić sposób przydziału obliczeń do dostępnych urządzeń, schemat wykorzystuje funkcje pozwalające określić szybkość i wydajność energetyczną, które może wykonać każdy sterownik. Aby udostępnić te informacje, sterownik musi podać ustandaryzowane dane o wydajności oparte na wykonaniu zadań referencyjnych.
Aby określić wartości, które sterownik zwraca w odpowiedzi na żądanie IDevice::getCapabilities_1_3
, użyj aplikacji analizy porównawczej NNAPI do pomiaru wydajności odpowiednich typów danych. Do pomiaru skuteczności 32-bitowych wartości zmiennoprzecinkowych zalecamy modele MobileNet v1, v2, asr_float
i tts_float
, a kwantowe modele MobileNet v1 i v2 – w przypadku wartości 8-bitowych. Więcej informacji znajdziesz na stronie Android Machine Learning Test Suite.
W Androidzie 9 i starszych struktura Capabilities
zawiera informacje o wydajności sterownika tylko w przypadku tensorów zmiennoprzecinkowych i kwantowanych, a nie typów danych skalarnych.
W ramach procesu inicjalizacji platforma może wysyłać więcej zapytań o informacje, korzystając z funkcji IDevice::getType
, IDevice::getVersionString
, IDevice:getSupportedExtensions
i IDevice::getNumberOfCacheFilesNeeded
.
Po ponownym uruchomieniu usługi platforma 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
Framework określa, których urządzeń używać, gdy otrzyma żądanie od aplikacji. W Androidzie 10 aplikacje mogą wykrywać i określać urządzenia, których framework ma używać. Więcej informacji znajdziesz w artykule Wykrywanie i przypisywanie urządzeń.
Podczas kompilacji modelu platforma wysyła model do każdego kandydującego sterownika, wywołując metodę IDevice::getSupportedOperations_1_3
.
Każdy sterownik zwraca tablicę wartości logicznych wskazujących, które operacje modelu są obsługiwane. Sterownik może określić, że nie może wykonać danej operacji z różnych powodów. Na przykład:
- Sterownik nie obsługuje tego typu danych.
- Sterownik obsługuje tylko operacje z określonymi parametrami wejściowymi. Na przykład sterownik może obsługiwać operacje konwolucji 3 × 3 i 5 × 5, ale nie 7 × 7.
- Sterownik ma ograniczenia pamięci, które uniemożliwiają obsługę dużych wykresów lub danych wejściowych.
Podczas kompilacji dane wejściowe, dane wyjściowe i operandy wewnętrzne modelu (jak opisano w OperandLifeTime
) mogą mieć nieznane wymiary lub rangę. Więcej informacji znajdziesz w artykule Forma danych wyjściowych.
Framework instruuje każdy wybrany sterownik, aby przygotował się do wykonania podzbioru modelu, wywołując IDevice::prepareModel_1_3
.
Każdy sterownik kompiluje swój podzbiór. Kierowca może na przykład wygenerować kod lub utworzyć nową kopię wag. Ponieważ między kompilacją modelu a wykonywaniem żądań może upłynąć sporo czasu, podczas kompilacji nie należy przydzielać zasobów takich jak duże fragmenty pamięci urządzenia.
W przypadku powodzenia sterownik zwraca @1.3::IPreparedModel
uchwyt. Jeśli sterownik zwróci kod błędu podczas przygotowywania podzbioru modelu, platforma uruchomi cały model na procesorze.
Aby skrócić czas kompilacji podczas uruchamiania aplikacji, sterownik może przechowywać w pamięci podręcznej artefakty kompilacji. Więcej informacji znajdziesz w artykule Przyspieszanie kompilacji za pomocą pamięci podręcznej.
Realizacja
Gdy aplikacja prosi platformę o wykonanie żądania, platforma domyślnie wywołuje metodę HAL IPreparedModel::executeSynchronously_1_3
, aby wykonać synchroniczne wykonanie na gotowym modelu.
Żądanie może też być wykonywane asynchronicznie za pomocą metody execute_1_3
lub executeFenced
(patrz wykonanie w ramach ograniczeń) lub za pomocą wykonania w trybie burst.
Synchroniczne wywołania wykonania poprawiają wydajność i zmniejszają narzut 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, który powiadamia proces aplikacji o zakończeniu wykonania.
W przypadku asynchronicznej metody execute_1_3
kontrola wraca do procesu aplikacji po rozpoczęciu wykonywania, a sterownik musi powiadomić framework o zakończeniu wykonywania za pomocą funkcji @1.3::IExecutionCallback
.
Parametr Request
przekazany do metody wykonywania zawiera listę operandów wejściowych i wyjściowych użytych do wykonania. Pamięć, w której przechowywane są dane operandu, musi być w kolejności wiersza-duża, przy czym pierwszy wymiar będzie powtarzał najwolniejszy wymiar, i nie może mieć dopełnienia na końcu żadnego wiersza. Więcej informacji o typach operandów znajdziesz w opisie argumentów.
W przypadku sterowników NN HAL 1.2 lub nowszych po zakończeniu przetwarzania żądania do frameworku zwracane są stan błędu, kształt danych wyjściowych i informacje o czasie wykonania. Podczas wykonywania dane wyjściowe lub operandy wewnętrzne modelu mogą mieć co najmniej 1 nieznaną wymianę lub nieznaną rangę. Gdy co najmniej 1 operand wyjściowy ma nieznany wymiar lub pozycję, system musi zwrócić informacje wyjściowe o rozmiarach dynamicznych.
W przypadku sterowników z NN HAL 1.1 lub starszym 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 zostało ukończone. Operandy wewnętrzne mogą mieć co najmniej 1 nieznaną wymiar, ale muszą mieć określoną rangę.
W przypadku żądań użytkowników, które obejmują wiele sterowników, platforma odpowiada za rezerwowanie pamięci pośredniej i sekwencjonowanie wywołań każdego sterownika.
W tym samym miejscu @1.3::IPreparedModel
można inicjować równolegle wiele żądań.
Sterownik może wykonywać żądania równolegle lub sekwencyjnie.
Platforma może poprosić kierowcę o zatrzymanie więcej niż 1 przygotowanego modelu. Na przykład: przygotuj model m1
, przygotuj m2
, wykonaj żądanie r1
w przypadku m1
, wykonaj r2
w przypadku m2
, wykonaj r3
w przypadku m1
, wykonaj r4
w przypadku m2
, opublikuj (jak opisano w sekcji Usuwanie) m1
i opublikuj m2
.
Aby uniknąć powolnego pierwszego wykonania, które mogłoby pogorszyć wrażenia użytkownika (np. zacinanie się pierwszej klatki), sterownik powinien wykonywać większość inicjacji na etapie kompilacji. Inicjalizowanie podczas pierwszego uruchomienia powinno być ograniczone do działań, które negatywnie wpływają na stan systemu, gdy są wykonywane wcześnie, takich jak rezerwowanie dużych tymczasowych buforów lub zwiększanie częstotliwości zegara urządzenia. Sterowniki, które mogą przygotowywać tylko ograniczoną liczbę równoczesnych modeli, mogą wymagać inicjalizacji podczas pierwszego uruchomienia.
W Androidzie 10 lub nowszym, gdy wiele wykonań z tym samym przygotowanym modelem jest wykonywanych szybko po sobie, klient może użyć obiektu wykonania burst, aby komunikować się między procesami aplikacji a sterownika. Więcej informacji znajdziesz w artykule Wykonywanie w krótkim czasie i kolejki szybkich wiadomości.
Aby poprawić wydajność w krótkich odstępach czasu w przypadku wielu wykonań, sterownik może zachować tymczasowe bufory lub zwiększyć częstotliwość zegara. Zalecamy utworzenie wątku watchdog, aby zwolnić zasoby, jeśli po określonym czasie nie zostaną utworzone żadne nowe żądania.
Kształt wyjściowy
W przypadku żądań, w których co najmniej jeden operand wyjściowy nie ma określonych wymiarów, sterownik musi po wykonaniu wyświetlić listę kształtów danych wyjściowych zawierających informacje o wymiarach dla każdego argumentu wyjściowego. Więcej informacji o wymiarach znajdziesz tutaj: OutputShape
.
Jeśli wykonanie kończy się niepowodzeniem z powodu zbyt małego bufora wyjściowego, sterownik musi wskazać na liście kształtów wyjściowych, które operandy wyjściowe mają niewystarczający rozmiar bufora. Powinien on też zgłosić jak najwięcej informacji o wymiarach, używając 0 w przypadku nieznanych wymiarów.
Czas
W Androidzie 10 aplikacja może poprosić o czas wykonania, jeśli w ramach procesu kompilacji ma wskazane urządzenie do użycia. Szczegółowe informacje znajdziesz w sekcjach MeasureTiming
oraz Wykrywanie i przypisywanie urządzeń.
W takim przypadku podczas wykonywania żądania sterownik NN HAL 1.2 musi zmierzyć czas wykonania lub zgłosić UINT64_MAX
(aby wskazać, że czas trwania jest niedostępny). Sterownik powinien zminimalizować wszelkie kary za wydajność wynikające z mierzenia czasu trwania wykonania.
Sterownik podaje te czasy trwania w mikrosekundach w strukturze Timing
:
- Czas wykonywania na urządzeniu: nie uwzględnia czasu wykonywania w sterowniku, który działa na procesorze hosta.
- Czas wykonywania w sterowniku: uwzględnia czas wykonywania na urządzeniu.
Czasy trwania muszą uwzględniać czas zawieszenia wykonania, np. czas, gdy wykonanie zostało wywłaszczone przez inne zadania lub oczekiwanie na udostępnienie zasobu.
Jeśli sterownik nie został poproszony o zmierzenie czasu wykonywania lub jeśli wystąpi błąd wykonywania, musi zgłaszać czasy trwania jako UINT64_MAX
. Nawet jeśli sterownik został poproszony o zmierzenie czasu wykonania, może zamiast tego podać wartość UINT64_MAX
dla czasu na urządzeniu, czasu w sterowniku lub obu tych wartości. Gdy sterownik zgłasza oba czasy trwania jako wartość inną niż UINT64_MAX
, czas wykonywania w sterowniku musi być równy lub dłuższy niż czas na urządzeniu.
Wykonywanie w ogrodzie
W Androidzie 11 interfejs NNAPI umożliwia oczekiwanie na listę uchwytów sync_fence
i opcjonalnie zwracanie obiektu sync_fence
, który jest sygnalizowany po zakończeniu wykonania. Zmniejsza to wymagania związane z małymi modelami sekwencji i przypadkami użycia strumieniowania. Wykonywanie graniczne pozwala też na bardziej efektywną interoperacyjność z innymi komponentami, które mogą sygnalizować lub zaczekać na polecenie sync_fence
. Więcej informacji na temat sync_fence
znajdziesz w artykule o platformie synchronizacji.
W zabezpieczonym wykonaniu platforma wywołuje metodę IPreparedModel::executeFenced
, aby uruchomić ogrodzone, asynchroniczne wykonanie na gotowym modelu z wektorem zabezpieczeń przed synchronizacją. Jeśli zadanie asynchroniczne zostanie ukończone przed ponownym wywołaniem, dla funkcji sync_fence
może zostać zwrócony pusty uchwyt. Aby platforma mogła wysyłać zapytania o stan błędu i informacje o czasie trwania, musi też zostać zwrócony obiekt IFencedExecutionCallback
.
Po zakończeniu wykonania można wysłać zapytanie o te 2 wartości czasu, które mierzą czas wykonania: IFencedExecutionCallback::getExecutionInfo
.
timingLaunched
: czas od wywołania funkcjiexecuteFenced
do momentu, gdyexecuteFenced
zasygnalizuje zwrócony kodsyncFence
.timingFenced
: czas od momentu, w którym wszystkie blokady synchronizacji, na które czeka wykonanie, są sygnalizowane, gdyexecuteFenced
zasygnalizuje zwrócony błądsyncFence
.
Kontrola przepływu
W przypadku urządzeń z Androidem 11 lub nowszym NNAPI obejmuje 2 operacje przepływu sterowania (IF
i WHILE
), które przyjmują inne modele jako argumenty i wykonują je warunkowo (IF
) lub wielokrotnie (WHILE
). Więcej informacji o tym, jak to zrobić, znajdziesz w artykule na temat procesu sterowania.
Jakość usługi
W Androidzie 11 interfejs NNAPI zapewnia wyższą jakość usług (QoS), umożliwiając aplikacji wskazywanie względnych priorytetów modeli, maksymalnego czasu oczekiwania na przygotowanie modelu i maksymalnego czasu oczekiwania na zakończenie wykonania. Więcej informacji znajdziesz w artykule Jakość usługi.
Uporządkuj
Gdy aplikacja skończy korzystać z przygotowanego modelu, framework zwolni odwołanie do obiektu @1.3::IPreparedModel
. Gdy obiekt IPreparedModel
nie jest już używany, jest automatycznie usuwany w usłudze kierowcy, która go utworzyła. Zasoby specyficzne dla modelu można obecnie odzyskać podczas implementacji destruatora przez sterownik. Jeśli usługa kierowcy chce, aby obiekt IPreparedModel
został automatycznie zniszczony, gdy nie jest już potrzebny klientowi, nie może on zawierać żadnych odwołań do obiektu IPreparedModel
po zwróceniu obiektu IPreparedeModel
za pomocą interfejsu IPreparedModelCallback::notify_1_3
.
Wykorzystanie procesora
Sterowniki powinny używać procesora do konfigurowania obliczeń. Sterowniki nie powinny używać procesora do wykonywania obliczeń grafów, ponieważ koliduje to z prawidłowym przydzielaniem pracy przez platformę. Sterownik powinien zgłosić części, których nie obsługuje, i pozwolić, żeby platforma się zajęła.
Platforma zapewnia implementację procesora na potrzeby wszystkich operacji NNAPI z wyjątkiem operacji zdefiniowanych przez dostawcę. Więcej informacji znajdziesz w artykule Rozszerzenia dostawców.
Operacje wprowadzone w Androidzie 10 (poziom interfejsu API 29) mają tylko referencyjną implementację procesora, która pozwala sprawdzić, czy testy CTS i VTS są prawidłowe. Zoptymalizowane implementacje zawarte w ramkach uczenia maszynowego na urządzeniach mobilnych są preferowane w porównaniu z implementacją NNAPI na procesorze.
Funkcje użyteczności
Kod źródłowy NNAPI zawiera funkcje pomocnicze, których mogą używać usługi kierowcy.
Plik frameworks/ml/nn/common/include/Utils.h
zawiera różne funkcje użytkowe, takie jak te używane do logowania i konwersji między różnymi wersjami NN HAL.
VLogging:
VLOG
to makro kodu otaczające tagLOG
Androida, które rejestruje komunikat tylko wtedy, gdy we właściwościdebug.nn.vlog
jest ustawiony odpowiedni tag.initVLogMask()
musi być wywoływana przed każdym wywołaniem funkcjiVLOG
. Za pomocą makraVLOG_IS_ON
można sprawdzić, czy usługaVLOG
jest obecnie włączona. Dzięki temu skomplikowany kod logowania może być pomijany, jeśli nie jest potrzebny. Właściwość musi mieć jedną z tych wartości:- Pusty ciąg, który wskazuje, że nie ma potrzeby rejestrowania.
- Token
1
luball
, który wskazuje, że logowanie jest wymagane. - Lista tagów rozdzielonych spacjami, przecinkami lub dwukropkami wskazującymi, które logowanie należy wykonać. Tagi to
compilation
,cpuexe
,driver
,execution
,manager
imodel
.
compliantWithV1_*
: zwracatrue
, jeśli obiekt NN HAL można przekonwertować do tego samego typu w innej wersji HAL bez utraty informacji. Na przykład wywołanie funkcjicompliantWithV1_0
w elemencieV1_2::Model
zwraca wartośćfalse
, jeśli model zawiera operacje wprowadzone w NN HAL 1.1 lub NN HAL 1.2.convertToV1_*
: konwertuje obiekt NN HAL z jednej wersji na inną. Jeśli konwersja powoduje utratę informacji (czyli jeśli nowa wersja typu nie może w pełni reprezentować wartości), rejestrowane jest ostrzeżenie.Możliwości: do tworzenia pola
Capabilities::operandPerformance
możesz używać funkcjinonExtensionOperandPerformance
iupdate
.W zapytaniu można użyć właściwości o typach:
isExtensionOperandType
,isExtensionOperationType
,nonExtensionSizeOfData
,nonExtensionOperandSizeOfData
,nonExtensionOperandTypeIsScalar
,tensorHasUnspecifiedDimensions
.
Plik frameworks/ml/nn/common/include/ValidateHal.h
zawiera funkcje użytkowe służące do sprawdzania, czy obiekt NN HAL jest prawidłowy zgodnie ze specyfikacją jego wersji HAL.
validate*
: zwraca wartośćtrue
, jeśli obiekt NN HAL jest prawidłowy zgodnie ze specyfikacją jego wersji HAL. Typy OEM i typy rozszerzeń nie są weryfikowane. Na przykładvalidateModel
zwracafalse
, jeśli model zawiera operację odwołującą się do indeksu operandu, który nie istnieje, lub operacji, która nie jest obsługiwana w danej wersji HAL.
Plik frameworks/ml/nn/common/include/Tracing.h
zawiera makra, które upraszczają dodawanie informacji systracing do kodu sieci neuronowych.
Przykładem są wywołania makra NNTRACE_*
w przykładowym sterowniku.
Plik frameworks/ml/nn/common/include/GraphDump.h
zawiera funkcję narzędzia do zrzutu zawartości pliku Model
w formie graficznej na potrzeby debugowania.
graphDump
: zapisuje reprezentację modelu w formacie Graphviz (.dot
) w wybranym strumieniu (jeśli został podany) lub w logcat (jeśli nie został podany żaden strumień).
Weryfikacja
Aby przetestować implementację NNAPI, użyj testów VTS i CTS dostępnych w platformie Androida. VTS testuje sterowniki bezpośrednio (bez używania frameworku), a CTS testuje je pośrednio za pomocą frameworku. Sprawdzą one każdą metodę interfejsu API i sprawdzają, czy wszystkie operacje obsługiwane przez sterowniki działają prawidłowo, a także dają wyniki spełniające wymagania dotyczące dokładności.
Wymagania dotyczące dokładności w CTS i VTS w przypadku NNAPI:
Liczba zmiennoprzecinkowa: abs(expected - actual) <= atol + rtol * abs(expected); gdzie:
- W przypadku fp32, atol = 1e-5f, rtol = 5.0f * 1.1920928955078125e-7
- W przypadku fp16, atol = rtol = 5.0f * 0,0009765625f
Zakwantowana: przesunięcie o 1 (z wyjątkiem
mobilenet_quantized
, która jest przesunięta o 3).Wartość logiczna: dopasowanie ścisłe.
Jednym ze sposobów testowania NNAPI przez CTS jest generowanie stałych, pseudolosowych grafów, które służą do testowania i porównywania wyników wykonania każdego sterownika z implementacją referencyjną NNAPI. Jeśli sterowniki z NN HAL 1.2 lub nowszym nie spełniają kryteriów dokładności, CTS zgłasza błąd i wypisuje plik specyfikacji nieudanego modelu w folderze /data/local/tmp
na potrzeby debugowania.
Więcej informacji o kryteriach dokładności znajdziesz w artykułach TestRandomGraph.cpp
i TestHarness.h
.
Testowanie fuzz
Celem testowania fuzz jest znajdowanie awarii, stwierdzeń, naruszeń pamięci lub ogólnie nieokreślonego zachowania w testowanym kodzie z powodu czynników takich jak nieoczekiwane dane wejściowe. Do testowania rozmycia NNAPI Android używa testów opartych na libFuzzer, które skutecznie ukrywają dane, ponieważ do generowania nowych losowych danych wejściowych wykorzystują pokrycie wierszy z poprzednich przypadków testowych. Na przykład libFuzzer preferuje przypadki testowe, które działają na nowych liniach kodu. To znacznie skraca czas potrzebny na znalezienie problematycznego kodu.
Aby przeprowadzić testy zamazania w celu zweryfikowania implementacji sterownika, zmodyfikuj frameworks/ml/nn/runtime/test/android_fuzzing/DriverFuzzTest.cpp
w narzędziu testowym libneuralnetworks_driver_fuzzer
w AOSP, tak aby zawierał kod sterownika. Więcej informacji o testowaniu rozmycia NNAPI znajdziesz tutaj: frameworks/ml/nn/runtime/test/android_fuzzing/README.md
.
Bezpieczeństwo
Procesy aplikacji komunikują się bezpośrednio z procesem kierowcy, dlatego kierowcy muszą zweryfikować argumenty otrzymywanych wywołań. Ta weryfikacja jest przeprowadzana przez VTS. Kod weryfikacyjny znajduje się w frameworks/ml/nn/common/include/ValidateHal.h
.
Kierowcy powinni też zadbać o to, aby aplikacje nie zakłócały działania innych aplikacji na tym samym urządzeniu.
(pakiet) Android Machine Learning Test Suite
Zbiór testów uczenia maszynowego na Androida (MLTS) to test porównawczy NNAPI zawarty w CTS i VTS, który służy do sprawdzania dokładności rzeczywistych modeli na urządzeniach dostawców. W ramach testów porównawczych ocenia się czas oczekiwania i dokładność oraz porównuje wyniki sterowników z wynikami za pomocą narzędzia TF Lite uruchomionego na procesorze dla tego samego modelu i zbiorów danych. Dzięki temu dokładność sterownika nie jest gorsza niż w implementacji referencyjnej dla procesora.
Programiści platformy Android korzystają z MLTS do oceny opóźnień i dokładności sterowników.
Benchmark NNAPI można znaleźć w 2 projektach w AOSP:
platform/test/mlts/benchmark
(aplikacja referencyjna)platform/test/mlts/models
(modele i zbiory danych)
Modele i zbiory danych
Test porównawczy NNAPI korzysta z tych modeli i zbiorów danych.
- MobileNetV1 z użyciem kodowania stałopółtonowego i u8 w różnych rozmiarach, uruchomione na małej podzbiorze (1500 obrazów) zbioru Open Images Dataset w wersji 4.
- Obiekty zmiennoprzecinkowe MobileNetV2 i u8 poddane kwantyzacji w różnych rozmiarach są analizowane na niewielkim podzbiorze (1500 obrazów) zbioru danych Open Images v4.
- Zamiana tekstu na mowę z modelu akustycznego opartego na pamięci krótkoterminowej (LSTM) na niewielkim podzbiorze grupy Arktyki CMU.
- Model akustyczny oparty na LSTM do automatycznego rozpoznawania mowy, uruchomiony na niewielkim podzbiorze zbioru danych LibriSpeech.
Więcej informacji: platform/test/mlts/models
.
Testy obciążeniowe
Pakiet testów uczenia maszynowego na Androidzie obejmuje serię testów odporności na awarie, które mają na celu weryfikację odporności sterowników w warunkach intensywnego użytkowania lub w przypadkach szczególnych zachowań klientów.
Wszystkie testy awarii obejmują te funkcje:
- Wykrywanie zawieszania się: jeśli klient NNAPI zawiesi się podczas testu, test zakończy się niepowodzeniem z powodem
HANG
, a pakiet testów przejdzie do następnego testu. - Wykrywanie awarii klienta NNAPI: testy przetrwają awarie klienta i testy kończą się niepowodzeniem z powodem
CRASH
. - Wykrywanie awarii kierowców: testy wykrywają wypadek kierowcy, który powoduje awarię wywołania NNAPI. Pamiętaj, że w procesach sterownika mogą występować awarie, które nie powodują awarii NNAPI ani nie powodują niepowodzenia testu. Aby uwzględnić tego typu awarię, zalecamy uruchomienie polecenia
tail
w logu systemowym w przypadku błędów lub awarii związanych z sterownikami. - Kierowanie na wszystkie dostępne akceleratory: testy są przeprowadzane na wszystkich dostępnych komponentach.
Wszystkie testy awarii mogą mieć 4 możliwe wyniki:
SUCCESS
: wykonanie zakończyło się bez błędów.FAILURE
: nie udało się wykonać. Zwykle jest to spowodowane błędem podczas testowania modelu, który wskazuje, że sterownik nie skompilował lub nie wykonał modelu.HANG
: proces testowy nie odpowiada.CRASH
: proces testowania uległ awarii.
Więcej informacji o testach obciążeniowych i pełną listę testów awarii znajdziesz w artykule platform/test/mlts/benchmark/README.txt
.
Używanie MTLS
Aby korzystać z MLTS:
- Podłącz urządzenie docelowe do stacji roboczej i upewnij się, że jest ono osiągalne za pomocą narzędzia adb.
Jeśli podłączone jest więcej niż 1 urządzenie, wyeksportuj zmienną środowiskową
ANDROID_SERIAL
urządzenia docelowego. cd
do katalogu źródłowego najwyższego poziomu Androida.source build/envsetup.sh lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available. ./test/mlts/benchmark/build_and_run_benchmark.sh
Po zakończeniu testu porównawczego wyniki są wyświetlane w postaci strony HTML i przekazywane do
xdg-open
.
Więcej informacji: platform/test/mlts/benchmark/README.txt
.
Wersje HAL Neural Networks
W tej sekcji opisujemy zmiany wprowadzone w wersjach HAL Androida i Neural Networks.
Android 11
Android 11 wprowadza NN HAL 1.3, co obejmuje następujące ważne zmiany.
- Obsługa zaokrągleń 8-bitowych z znakami w NNAPI. Dodaje typ operandu
TENSOR_QUANT8_ASYMM_SIGNED
. Sterowniki z NN HAL 1.3, które obsługują operacje z kwantyzacją bez podpisu, muszą też obsługiwać podpisane warianty tych operacji. Podczas wykonywania wersji z podpisem i bez podpisu większości operacji kwantowanych sterowniki muszą dawać takie same wyniki z dokładnością do przesunięcia o 128. Od tego wymagania jest 5 wyjątków:CAST
,HASHTABLE_LOOKUP
,LSH_PROJECTION
,PAD_V2
iQUANTIZED_16BIT_LSTM
. OperacjaQUANTIZED_16BIT_LSTM
nie obsługuje podpisanych operandów, a pozostałe 4 operacje obsługują kwantyzację z podpisem, ale nie wymagają, aby wyniki były takie same. - Obsługa odizolowanych wykonań, w których framework wywołuje metodę
IPreparedModel::executeFenced
, aby uruchomić odizolowane, asynchroniczne wykonanie przygotowanego modelu z wektorem ogrodzeń synchronizacji, na które ma czekać. Więcej informacji znajdziesz w artykule Wykonywanie w ogrodzie. - Obsługa przepływu sterowania. Dodaje operacje
IF
iWHILE
, które przyjmują inne modele jako argumenty i wykonują je warunkowo (IF
) lub wielokrotnie (WHILE
). Więcej informacji znajdziesz w artykule Przepływ sterowania. - Poprawiona jakość usług (QoS), ponieważ aplikacje mogą wskazywać względne priorytety swoich modeli, maksymalny spodziewany czas przygotowania modelu i maksymalny spodziewany czas wykonania wykonania. Więcej informacji znajdziesz w artykule Jakość usług.
- Obsługa domen pamięci, które udostępniają interfejsy rozdzielające dla buforów zarządzanych przez sterownika. Umożliwia to przekazywanie danych natywnych urządzeń w ramach poszczególnych wykonań, co eliminuje niepotrzebne kopiowanie i przekształcanie danych między kolejnymi wykonaniami na tym samym sterowniku. Więcej informacji znajdziesz w artykule Pamięć domen.
Android 10
Android 10 wprowadza interfejs NN HAL 1.2, który zawiera te ważne zmiany:
- Struktura
Capabilities
obejmuje wszystkie typy danych, w tym typy danych skalarnych, i reprezentuje niezrelaksowaną wydajność przy użyciu pól wektorowych, a nie nazwanych. - Metody
getVersionString
igetType
umożliwiają frameworkowi pobieranie informacji o typie urządzenia (DeviceType
) i wersji. Zobacz Wykrywanie i przypisywanie urządzeń. - Domyślnie metoda
executeSynchronously
jest wywoływana, aby wykonywać wykonanie synchronicznie. Metodaexecute_1_2
informuje platformę o niesynchronicznym wykonywaniu. Zobacz Wykonanie. - Parametr
MeasureTiming
ma wartośćexecuteSynchronously
,execute_1_2
lub wykonanie w trybie burst określa, czy sterownik ma mierzyć czas trwania wykonania. Wyniki są raportowane w strukturzeTiming
. Zobacz Harmonogram. - Obsługa wykonywania, w którym co najmniej 1 wynik operacji ma nieznaną wymiar lub rangę. Zobacz kształt wyjściowy.
- Obsługa rozszerzeń dostawcy, czyli zbiorów operacji i typów danych zdefiniowanych przez dostawcę. Sterownik zgłasza obsługiwane rozszerzenia za pomocą metody
IDevice::getSupportedExtensions
. Zobacz rozszerzenia dostawcy. - Możliwość sterowania przez obiekt burst zbiorem operacji burst za pomocą kolejek szybkich wiadomości (FMQ) w celu komunikacji między procesami aplikacji i sterownika, co zmniejsza opóźnienie. Zobacz Wykonywanie w skoku i kolejki szybkich wiadomości.
- Obsługa AHardwareBuffer, która umożliwia sterownikowi wykonywanie wykonań bez kopiowania danych. Zobacz AHardwareBuffer.
- Ulepszona obsługa buforowania artefaktów kompilacji, która pozwala skrócić czas kompilacji podczas uruchamiania aplikacji. Zobacz Pamięć podręczna kompilacji.
Android 10 wprowadza te typy i operacje 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
-
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. Są one głównie związane z następującymi kwestiami:
- Obsługa układu pamięci NCHW
- Obsługa tensorów o rangach innych niż 4 w operacjach softmax i normalizacji
- Obsługa rozszerzonych splotów
- Obsługa danych wejściowych z kwantyzacją mieszaną w regionie
ANEURALNETWORKS_CONCATENATION
Poniższa lista przedstawia operacje zmodyfikowane w Androidzie 10. Szczegółowe informacje o zmianach znajdziesz w sekcji 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
Android 9
NN HAL 1.1 został wprowadzony w Androidzie 9 i zawiera te ważne zmiany:
IDevice::prepareModel_1_1
zawiera parametrExecutionPreference
. Kierowca może wykorzystać tę funkcję, aby dostosować przygotowanie, wiedząc, że aplikacja woli oszczędzać baterię lub będzie uruchamiać model w szybkich kolejnych wywołaniach.- Dodano 9 nowych operacji:
BATCH_TO_SPACE_ND
,DIV
,MEAN
,PAD
,SPACE_TO_BATCH_ND
,SQUEEZE
,STRIDED_SLICE
,SUB
,TRANSPOSE
. - Aplikacja może określić, że obliczenia 32-bitowej liczby zmiennoprzecinkowej mogą być wykonywane przy użyciu zakresu lub dokładności 16-bitowej liczby zmiennoprzecinkowej, ustawiając wartość
Model.relaxComputationFloat32toFloat16
natrue
. StrukturaCapabilities
zawiera dodatkowe polerelaxedFloat32toFloat16Performance
, dzięki któremu kierowca może raportować do platformy dane o swojskiej wydajności.
Android 8.1
Pierwsza wersja HAL dla sieci neuronowych (1.0) została wydana w Androidzie 8.1. Więcej informacji znajdziesz w sekcji /neuralnetworks/1.0/
.