Các tiện ích của nhà cung cấp Neural Networks API (NNAPI) (ra mắt trong Android 10) là tập hợp các thao tác và kiểu dữ liệu do nhà cung cấp xác định. Trên các thiết bị chạy NN HAL 1.2 trở lên, trình điều khiển có thể cung cấp các hoạt động tuỳ chỉnh có tăng tốc phần cứng bằng cách hỗ trợ các tiện ích tương ứng của nhà cung cấp. Các tiện ích của nhà cung cấp không sửa đổi hành vi của các thao tác hiện có.
Các tiện ích của nhà cung cấp cung cấp một giải pháp thay thế có cấu trúc hơn cho hoạt động và kiểu dữ liệu của OEM. Các tiện ích này đã ngừng hoạt động trong Android 10. Để biết thêm thông tin, hãy xem phần Các loại dữ liệu và hoạt động của OEM.
Danh sách cho phép sử dụng tiện ích
Các tiện ích của nhà cung cấp chỉ có thể được dùng bởi các ứng dụng Android và tệp nhị phân gốc được chỉ định rõ ràng trên các phân vùng /product
, /vendor
, /odm
và /data
.
Các ứng dụng và tệp nhị phân gốc nằm trên phân vùng /system
không thể sử dụng các tiện ích của nhà cung cấp.
Danh sách các ứng dụng và tệp nhị phân Android được phép sử dụng các tiện ích của nhà cung cấp NNAPI được lưu trữ trong /vendor/etc/nnapi_extensions_app_allowlist
. Mỗi dòng trong tệp chứa một mục nhập mới. Một mục có thể là đường dẫn nhị phân gốc có tiền tố là dấu gạch chéo (/), ví dụ: /data/foo
hoặc tên của một gói ứng dụng Android, ví dụ: com.foo.bar
.
Danh sách cho phép được thực thi từ thư viện dùng chung thời gian chạy NNAPI. Thư viện này bảo vệ chống lại việc sử dụng tình cờ nhưng không chống lại hành vi cố ý lách luật của một ứng dụng trực tiếp sử dụng giao diện HAL trình điều khiển NNAPI.
Định nghĩa về tiện ích của nhà cung cấp
Nhà cung cấp tạo và duy trì một tệp tiêu đề có định nghĩa về tiện ích. Bạn có thể xem ví dụ đầy đủ về định nghĩa tiện ích trong example/fibonacci/FibonacciExtension.h
.
Mỗi tiện ích đều phải có một tên riêng biệt bắt đầu bằng tên miền đảo ngược của nhà cung cấp.
const char EXAMPLE_EXTENSION_NAME[] = "com.example.my_extension";
Tên này đóng vai trò là không gian tên cho các thao tác và kiểu dữ liệu. NNAPI sử dụng tên này để phân biệt các tiện ích của nhà cung cấp.
Các thao tác và kiểu dữ liệu được khai báo theo cách tương tự như trong 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,
};
Một thao tác mở rộng có thể sử dụng bất kỳ loại toán hạng nào, bao gồm cả các loại toán hạng không mở rộng và các loại toán hạng từ các tiện ích khác. Khi sử dụng một loại toán hạng từ một tiện ích khác, trình điều khiển phải hỗ trợ tiện ích đó.
Các tiện ích cũng có thể khai báo cấu trúc tuỳ chỉnh để đi kèm với các toán hạng của tiện ích.
/**
* Quantization parameters for {@link EXAMPLE_TENSOR}.
*/
typedef struct ExampleTensorParams {
double scale;
int64_t zeroPoint;
} ExampleTensorParams;
Sử dụng các tiện ích trong ứng dụng NNAPI
Tệp runtime/include/NeuralNetworksExtensions.h
(C API) hỗ trợ tiện ích thời gian chạy. Phần này cung cấp thông tin tổng quan về C API.
Để kiểm tra xem một thiết bị có hỗ trợ tiện ích hay không, hãy dùng ANeuralNetworksDevice_getExtensionSupport
.
bool isExtensionSupported;
CHECK_EQ(ANeuralNetworksDevice_getExtensionSupport(device, EXAMPLE_EXTENSION_NAME,
&isExtensionSupported),
ANEURALNETWORKS_NO_ERROR);
if (isExtensionSupported) {
// The device supports the extension.
...
}
Để tạo một mô hình có toán hạng mở rộng, hãy dùng ANeuralNetworksModel_getExtensionOperandType
để lấy loại toán hạng và gọi 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);
Bạn có thể dùng ANeuralNetworksModel_setOperandExtensionData
để liên kết dữ liệu bổ sung với một toán hạng của tiện ích.
ExampleTensorParams params{
.scale = 0.5,
.zeroPoint = 128,
};
CHECK_EQ(ANeuralNetworksModel_setOperandExtensionData(model, operandIndex, ¶ms, sizeof(params)),
ANEURALNETWORKS_NO_ERROR);
Để tạo một mô hình bằng thao tác mở rộng, hãy dùng ANeuralNetworksModel_getExtensionOperationType
để lấy loại thao tác và gọi 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);
Thêm tính năng hỗ trợ tiện ích vào trình điều khiển NNAPI
Người lái xe báo cáo các tiện ích được hỗ trợ thông qua phương thức IDevice::getSupportedExtensions
. Danh sách được trả về phải chứa một mục mô tả từng tiện ích được hỗ trợ.
Extension {
.name = EXAMPLE_EXTENSION_NAME,
.operandTypes = {
{
.type = EXAMPLE_SCALAR,
.isTensor = false,
.byteSize = 8,
},
{
.type = EXAMPLE_TENSOR,
.isTensor = true,
.byteSize = 8,
},
},
}
Trong số 32 bit dùng để xác định các loại và thao tác, Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX
bit cao là tiền tố tiện ích và Model::ExtensionTypeEncoding::LOW_BITS_TYPE
bit thấp biểu thị loại hoặc thao tác của tiện ích.
Khi xử lý một thao tác hoặc kiểu toán hạng, trình điều khiển phải kiểm tra tiền tố của tiện ích. Nếu tiền tố tiện ích có giá trị khác 0, thì kiểu thao tác hoặc toán hạng là kiểu tiện ích. Nếu giá trị là 0
, thì thao tác hoặc loại toán hạng không phải là loại tiện ích.
Để liên kết tiền tố với tên tiện ích, hãy tra cứu tiền tố đó trong model.extensionNameToPrefix
.
Mối liên kết từ tiền tố đến tên tiện ích là mối tương ứng một-một (song ánh xạ) cho một mô hình nhất định. Các giá trị tiền tố khác nhau có thể tương ứng với cùng một tên tiện ích trong các mô hình khác nhau.
Trình điều khiển phải xác thực các thao tác và kiểu dữ liệu của tiện ích vì thời gian chạy NNAPI không thể xác thực các thao tác và kiểu dữ liệu cụ thể của tiện ích.
Toán hạng tiện ích có thể có dữ liệu được liên kết trong operand.extraParams.extension
, mà thời gian chạy coi là một blob dữ liệu thô có kích thước tuỳ ý.
Các loại dữ liệu và hoạt động của OEM
NNAPI có một thao tác OEM và các loại dữ liệu OEM để cho phép nhà sản xuất thiết bị cung cấp chức năng tuỳ chỉnh dành riêng cho trình điều khiển. Các kiểu dữ liệu và thao tác này chỉ được dùng bởi các ứng dụng OEM. Ngữ nghĩa của thao tác và kiểu dữ liệu OEM là dành riêng cho OEM và có thể thay đổi bất cứ lúc nào. Các loại dữ liệu và thao tác OEM được mã hoá bằng OperationType::OEM_OPERATION
, OperandType::OEM
và OperandType::TENSOR_OEM_BYTE
.