Android 10에 도입된 NNAPI(신경망 API) 공급업체 확장은 공급업체에서 정의한 작업 및 데이터 유형의 모음입니다. NN HAL 1.2 이상을 실행하는 장치에서 드라이버는 해당 공급업체 확장을 지원하여 사용자 지정 하드웨어 가속 작업을 제공할 수 있습니다. 공급업체 확장은 기존 작업의 동작을 수정하지 않습니다.
공급업체 확장 프로그램은 Android 10에서 더 이상 사용되지 않는 OEM 작업 및 데이터 유형에 대한 보다 구조화된 대안을 제공합니다. 자세한 내용은 OEM 작업 및 데이터 유형 을 참조하세요.
확장 프로그램 사용 허용 목록
공급업체 확장은 /product
, /vendor
, /odm
및 /data
파티션에서 명시적으로 지정된 Android 앱 및 기본 바이너리에서만 사용할 수 있습니다. /system
파티션에 있는 앱 및 기본 바이너리는 공급업체 확장을 사용할 수 없습니다.
NNAPI 공급업체 확장을 사용하도록 허용된 Android 앱 및 바이너리 목록은 /vendor/etc/nnapi_extensions_app_allowlist
에 저장됩니다. 파일의 각 줄에는 새 항목이 포함됩니다. 항목은 접두사가 슬래시(/)인 기본 바이너리 경로(예: /data/foo
) 또는 Android 앱 패키지의 이름(예: com.foo.bar
)일 수 있습니다.
허용 목록은 NNAPI 런타임 공유 라이브러리에서 시행됩니다. 이 라이브러리는 우발적인 사용으로부터 보호하지만 NNAPI 드라이버 HAL 인터페이스를 직접 사용하는 앱의 의도적인 우회에 대해서는 보호하지 않습니다.
공급업체 확장 정의
공급업체는 확장 정의가 포함된 헤더 파일을 만들고 유지 관리합니다. 확장 정의의 완전한 예는 example/fibonacci/FibonacciExtension.h
에서 찾을 수 있습니다.
각 확장에는 공급업체의 역방향 도메인 이름으로 시작하는 고유한 이름이 있어야 합니다.
const char EXAMPLE_EXTENSION_NAME[] = "com.example.my_extension";
이름은 작업 및 데이터 유형에 대한 네임스페이스 역할을 합니다. NNAPI는 이 이름을 사용하여 공급업체 확장을 구별합니다.
작업 및 데이터 유형은 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,
};
확장 연산은 비확장 피연산자 유형과 다른 확장의 피연산자 유형을 포함하여 모든 피연산자 유형을 사용할 수 있습니다. 다른 확장의 피연산자 유형을 사용할 때 드라이버는 다른 확장을 지원해야 합니다.
확장은 확장 피연산자를 동반하는 사용자 지정 구조를 선언할 수도 있습니다.
/**
* Quantization parameters for {@link EXAMPLE_TENSOR}.
*/
typedef struct ExampleTensorParams {
double scale;
int64_t zeroPoint;
} ExampleTensorParams;
NNAPI 클라이언트에서 확장 사용
runtime/include/NeuralNetworksExtensions.h
(C API) 파일은 런타임 확장 지원을 제공합니다. 이 섹션에서는 C API에 대한 개요를 제공합니다.
장치가 확장을 지원하는지 확인하려면 ANeuralNetworksDevice_getExtensionSupport
를 사용하십시오.
bool isExtensionSupported;
CHECK_EQ(ANeuralNetworksDevice_getExtensionSupport(device, EXAMPLE_EXTENSION_NAME,
&isExtensionSupported),
ANEURALNETWORKS_NO_ERROR);
if (isExtensionSupported) {
// The device supports the extension.
...
}
확장 피연산자가 있는 모델을 빌드하려면 ANeuralNetworksModel_getExtensionOperandType
을 사용하여 피연산자 유형을 얻고 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);
선택적으로 ANeuralNetworksModel_setOperandExtensionData
를 사용하여 추가 데이터를 확장 피연산자와 연결합니다.
ExampleTensorParams params{
.scale = 0.5,
.zeroPoint = 128,
};
CHECK_EQ(ANeuralNetworksModel_setOperandExtensionData(model, operandIndex, ¶ms, sizeof(params)),
ANEURALNETWORKS_NO_ERROR);
확장 작업으로 모델을 빌드하려면 ANeuralNetworksModel_getExtensionOperationType
을 사용하여 작업 유형을 얻고 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);
NNAPI 드라이버에 확장 지원 추가
드라이버는 IDevice::getSupportedExtensions
메서드를 통해 지원되는 확장을 보고합니다. 반환된 목록에는 지원되는 각 확장을 설명하는 항목이 포함되어야 합니다.
Extension {
.name = EXAMPLE_EXTENSION_NAME,
.operandTypes = {
{
.type = EXAMPLE_SCALAR,
.isTensor = false,
.byteSize = 8,
},
{
.type = EXAMPLE_TENSOR,
.isTensor = true,
.byteSize = 8,
},
},
}
유형 및 작업을 식별하는 데 사용되는 32비트 중 상위 Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX
비트는 확장 접두사 이고 하위 Model::ExtensionTypeEncoding::LOW_BITS_TYPE
비트는 확장의 유형 또는 작업을 나타냅니다.
연산 또는 피연산자 유형을 처리할 때 드라이버는 확장 접두사를 확인해야 합니다. 확장 접두사가 0이 아닌 값을 갖는 경우 연산 또는 피연산자 유형은 확장 유형입니다. 값이 0
이면 연산 또는 피연산자 유형은 확장 유형이 아닙니다.
접두사를 확장명에 매핑하려면 model.extensionNameToPrefix
에서 찾아보세요. 접두사에서 확장명으로의 매핑은 주어진 모델에 대한 일대일 대응(전사)입니다. 다른 접두사 값은 다른 모델의 동일한 확장 이름에 해당할 수 있습니다.
NNAPI 런타임은 특정 확장 작업 및 데이터 유형의 유효성을 검사할 수 없기 때문에 드라이버는 확장 작업 및 데이터 유형의 유효성을 검사해야 합니다.
확장 피연산자는 operand.extraParams.extension
에 연결된 데이터를 가질 수 있으며 런타임은 이 데이터를 임의 크기의 원시 데이터 덩어리로 처리합니다.
OEM 작업 및 데이터 유형
NNAPI에는 장치 제조업체가 사용자 지정 드라이버별 기능을 제공할 수 있도록 하는 OEM 작업 및 OEM 데이터 유형이 있습니다. 이러한 작업 및 데이터 형식은 OEM 응용 프로그램에서만 사용됩니다. OEM 작업 및 데이터 유형의 의미는 OEM에 따라 다르며 언제든지 변경될 수 있습니다. OEM 작업 및 데이터 유형은 OperationType::OEM_OPERATION
, OperandType::OEM
및 OperandType::TENSOR_OEM_BYTE
를 사용하여 인코딩됩니다.