Rozszerzenia dostawcy interfejsu Neural Networks API (NNAPI) wprowadzone w Androida 10 zbiory działań i typów danych zdefiniowanych przez dostawcę. Na urządzeniach z systemem NN HAL w wersji 1.2 lub nowszej, sterowniki mogą umożliwiać niestandardowe przyspieszanie sprzętowe operacji przez obsługujące odpowiednie rozszerzenia dostawców. Rozszerzenia dostawców nie modyfikują dla obecnych operacji.
Rozszerzenia dla dostawców zapewniają bardziej uporządkowaną alternatywę dla działalności OEM. typy danych, które zostały wycofane w Androidzie 10. Więcej informacji: Operacje OEM i typy danych.
Lista dozwolonych na temat użycia rozszerzeń
Rozszerzenia dostawców mogą być używane tylko przez wyraźnie określone aplikacje na Androida
natywne pliki binarne na partycjach /product
, /vendor
, /odm
i /data
.
Aplikacje i natywne pliki binarne znajdujące się na partycji /system
nie mogą korzystać z usług dostawcy
rozszerzeń.
Lista aplikacji na Androida i plików binarnych, które mogą używać rozszerzeń dostawcy NNAPI, to
przechowywane w /vendor/etc/nnapi_extensions_app_allowlist
. Każdy wiersz w pliku
zawiera nowy wpis. Wpis może być natywną ścieżką binarną poprzedzoną prefiksem
ukośnik (/), np. /data/foo
, lub nazwa pakietu aplikacji na Androida, na przykład
na przykład com.foo.bar
.
Lista dozwolonych jest egzekwowana z zasobów wspólnych środowiska wykonawczego NNAPI. Ta biblioteka chroni przed przypadkowym użyciem, ale nie przed bezpośrednio przez interfejs HAL sterownika NNAPI.
Definicja rozszerzenia dostawcy
Dostawca tworzy i utrzymuje plik nagłówka z definicją rozszerzenia. O
pełny przykład definicji rozszerzenia można znaleźć w
example/fibonacci/FibonacciExtension.h
Każde rozszerzenie musi mieć unikalną nazwę, która zaczyna się od odwrotnej nazwy domeny od dostawcy.
const char EXAMPLE_EXTENSION_NAME[] = "com.example.my_extension";
Jest to przestrzeń nazw operacji i typów danych. NNAPI używa tego nazwy pozwalającej rozróżnić rozszerzenia dostawcy.
Operacje i typy danych są deklarowane w sposób podobny do tych w
runtime/include/NeuralNetworks.h
enum {
/**
* A custom scalar type.
*/
EXAMPLE_SCALAR = 0,
/**
* A custom tensor type.
*
* Attached to this tensor is {@link ExampleTensorParams}.
*/
EXAMPLE_TENSOR = 1,
};
enum {
/**
* Computes example function.
*
* Inputs:
* * 0: A scalar of {@link EXAMPLE_SCALAR}.
*
* Outputs:
* * 0: A tensor of {@link EXAMPLE_TENSOR}.
*/
EXAMPLE_FUNCTION = 0,
};
Operacja rozszerzenia może używać dowolnego typu operandu, w tym operandu bez rozszerzenia i typy operandów z innych rozszerzeń. W przypadku użycia typu operandu z argumentu z innego rozszerzenia, sterownik musi je obsługiwać.
Rozszerzenia mogą też deklarować niestandardowe struktury, aby towarzyszyć operandom rozszerzenia.
/**
* Quantization parameters for {@link EXAMPLE_TENSOR}.
*/
typedef struct ExampleTensorParams {
double scale;
int64_t zeroPoint;
} ExampleTensorParams;
Używanie rozszerzeń w klientach NNAPI
runtime/include/NeuralNetworksExtensions.h
(C API) zapewnia obsługę rozszerzenia środowiska wykonawczego. W tej sekcji znajdziesz
o C API.
Aby sprawdzić, czy urządzenie obsługuje rozszerzenie, użyj
ANeuralNetworksDevice_getExtensionSupport
bool isExtensionSupported;
CHECK_EQ(ANeuralNetworksDevice_getExtensionSupport(device, EXAMPLE_EXTENSION_NAME,
&isExtensionSupported),
ANEURALNETWORKS_NO_ERROR);
if (isExtensionSupported) {
// The device supports the extension.
...
}
Aby utworzyć model z operandem rozszerzenia, użyj funkcji
ANeuralNetworksModel_getExtensionOperandType
w celu uzyskania typu operandu i wywołania
ANeuralNetworksModel_addOperand
int32_t type;
CHECK_EQ(ANeuralNetworksModel_getExtensionOperandType(model, EXAMPLE_EXTENSION_NAME, EXAMPLE_TENSOR, &type),
ANEURALNETWORKS_NO_ERROR);
ANeuralNetworksOperandType operandType{
.type = type,
.dimensionCount = dimensionCount,
.dimensions = dimensions,
};
CHECK_EQ(ANeuralNetworksModel_addOperand(model, &operandType), ANEURALNETWORKS_NO_ERROR);
Możesz też użyć funkcji
ANeuralNetworksModel_setOperandExtensionData
, aby powiązać dodatkowe dane z operandem rozszerzenia.
ExampleTensorParams params{
.scale = 0.5,
.zeroPoint = 128,
};
CHECK_EQ(ANeuralNetworksModel_setOperandExtensionData(model, operandIndex, ¶ms, sizeof(params)),
ANEURALNETWORKS_NO_ERROR);
Aby utworzyć model z operacją rozszerzenia, użyj funkcji
ANeuralNetworksModel_getExtensionOperationType
w celu uzyskania typu operacji i wywołania
ANeuralNetworksModel_addOperation
ANeuralNetworksOperationType type;
CHECK_EQ(ANeuralNetworksModel_getExtensionOperationType(model, EXAMPLE_EXTENSION_NAME, EXAMPLE_FUNCTION,
&type),
ANEURALNETWORKS_NO_ERROR);
CHECK_EQ(ANeuralNetworksModel_addOperation(model, type, inputCount, inputs, outputCount, outputs),
ANEURALNETWORKS_NO_ERROR);
Dodawanie obsługi rozszerzenia do sterownika NNAPI
Sterowniki zgłaszają obsługiwane rozszerzenia w
IDevice::getSupportedExtensions
. Zwrócona lista musi zawierać wpis opisujący każdą obsługiwaną listę
.
Extension {
.name = EXAMPLE_EXTENSION_NAME,
.operandTypes = {
{
.type = EXAMPLE_SCALAR,
.isTensor = false,
.byteSize = 8,
},
{
.type = EXAMPLE_TENSOR,
.isTensor = true,
.byteSize = 8,
},
},
}
Z 32 bitów używanych do identyfikowania typów i operacji wysoka
Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX
bity to rozszerzenie
prefiks i niski
Model::ExtensionTypeEncoding::LOW_BITS_TYPE
.
liczba bitów oznacza typ lub operację
rozszerzenia.
Podczas obsługi operacji lub typu operandu sterownik musi sprawdzić rozszerzenie
. Jeśli prefiks rozszerzenia ma wartość inną niż zero, operacja lub operand
jest typem rozszerzenia. Jeśli wartość to 0
, jest to typ operacji lub argumentu.
Nie jest typem rozszerzenia.
Aby zmapować prefiks na nazwę rozszerzenia, wyszukaj go w
model.extensionNameToPrefix
Mapowanie z prefiksu na nazwę rozszerzenia jest korespondencją „jeden do jednego”.
(bijekcjom) danego modelu. Różne wartości prefiksów mogą odpowiadać
z tą samą nazwą rozszerzenia w różnych modelach.
Sterownik musi zweryfikować operacje rozszerzenia i typy danych, ponieważ NNAPI środowisko wykonawcze nie może sprawdzać konkretnych operacji rozszerzeń ani typów danych.
operandy rozszerzenia mogą mieć powiązane dane w
operand.extraParams.extension
,
które środowisko wykonawcze traktuje jako nieprzetworzony obiekt blob danych o dowolnym rozmiarze.
Działania i typy danych OEM
NNAPI ma placówkę OEM i typy danych OEM, które pozwalają na
producentów urządzeń, by udostępnić im niestandardowe funkcje dostosowane do konkretnych sterowników. Te
operacji i typów danych
są używane tylko przez aplikacje OEM. Semantyka OEM
działania i typy danych są typowe dla OEM i mogą się zmienić w dowolnym momencie. OEM
operacji i typów danych są kodowane za pomocą OperationType::OEM_OPERATION
,
OperandType::OEM
i OperandType::TENSOR_OEM_BYTE
.