Tiện ích mở rộng nhà cung cấp

Tiện ích mở rộng của nhà cung cấp API Mạng thần kinh (NNAPI), được giới thiệu trong Android 10, là tập hợp các hoạt động và loại 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 tăng tốc phần cứng tùy chỉnh bằng cách hỗ trợ các tiện ích mở rộng tương ứng của nhà cung cấp. Tiện ích mở rộng của nhà cung cấp không sửa đổi hành vi của các hoạt động hiện có.

Tiện ích mở rộng của nhà cung cấp cung cấp giải pháp thay thế có cấu trúc hơn cho các loại dữ liệu và hoạt động OEM vốn không được dùng nữa trong Android 10. Để biết thêm thông tin, hãy xem các loại dữ liệu và hoạt động OEM .

Danh sách cho phép sử dụng tiện ích mở rộng

Tiện ích mở rộng của nhà cung cấp chỉ có thể được sử 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/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 tiện ích mở rộng 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 tiện ích mở rộng của nhà cung cấp NNAPI được lưu trữ trong /vendor/etc/nnapi_extensions_app_allowlist . Mỗi dòng của tập tin chứa một mục mới. Mục nhập 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 gói ứng dụng Android, chẳng hạn như com.foo.bar .

Danh sách cho phép được thực thi từ thư viện chia sẻ thời gian chạy NNAPI. Thư viện này bảo vệ khỏi việc vô tình sử dụng nhưng không chống lại hành vi cố ý phá hoại của một ứng dụng trực tiếp bằng giao diện HAL của trình điều khiển NNAPI.

Định nghĩa tiện ích mở rộng nhà cung cấp

Nhà cung cấp tạo và duy trì tệp tiêu đề có định nghĩa phần mở rộng. Bạn có thể tìm thấy ví dụ hoàn chỉnh về định nghĩa tiện ích mở rộng trong example/fibonacci/FibonacciExtension.h .

Mỗi tiện ích mở rộng phải có một tên duy nhất bắt đầu bằng tên miền ngược của nhà cung cấp.

const char EXAMPLE_EXTENSION_NAME[] = "com.example.my_extension";

Tên hoạt động như một không gian tên cho các hoạt động và kiểu dữ liệu. NNAPI sử dụng tên này để phân biệt giữa các phần mở rộng của nhà cung cấp.

Các hoạt động 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 loại toán hạng không mở rộng và các loại toán hạng từ các phần mở rộng khác. Khi sử dụng loại toán hạng từ tiện ích mở rộng khác, trình điều khiển phải hỗ trợ tiện ích mở rộng khác.

Các phần mở rộng cũng có thể khai báo các cấu trúc tùy chỉnh đi kèm với các toán hạng mở rộng.

/**
 * Quantization parameters for {@link EXAMPLE_TENSOR}.
 */
typedef struct ExampleTensorParams {
    double scale;
    int64_t zeroPoint;
} ExampleTensorParams;

Sử dụng tiện ích mở rộng trong máy khách NNAPI

Tệp runtime/include/NeuralNetworksExtensions.h (API C) cung cấp hỗ trợ tiện ích mở rộng thời gian chạy. Phần này cung cấp tổng quan về API C.

Để kiểm tra xem thiết bị có hỗ trợ tiện ích mở rộng hay không, hãy sử 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.
    ...
}

Để xây dựng mô hình có toán hạng mở rộng, hãy sử 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);

Tùy chọn sử dụng ANeuralNetworksModel_setOperandExtensionData để liên kết dữ liệu bổ sung với toán hạng mở rộng.

ExampleTensorParams params{
        .scale = 0.5,
        .zeroPoint = 128,
};
CHECK_EQ(ANeuralNetworksModel_setOperandExtensionData(model, operandIndex, &params, sizeof(params)),
         ANEURALNETWORKS_NO_ERROR);

Để xây dựng mô hình có thao tác mở rộng, hãy sử dụng ANeuralNetworksModel_getExtensionOperationType để lấy loại hoạt động 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 hỗ trợ tiện ích mở rộng cho trình điều khiển NNAPI

Trình điều khiển báo cáo các tiện ích mở rộng được hỗ trợ thông qua phương thức IDevice::getSupportedExtensions . Danh sách trả về phải chứa mục mô tả từng tiện ích mở rộng đượ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 được sử dụng để xác định loại và hoạt động, các bit Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX cao là tiền tố mở rộng và các bit Model::ExtensionTypeEncoding::LOW_BITS_TYPE thấp đại diện cho loại hoặc hoạt động của tiện ích mở rộng.

Khi xử lý một thao tác hoặc loại toán hạng, trình điều khiển phải kiểm tra tiền tố mở rộng. Nếu tiền tố mở rộng có giá trị khác 0 thì loại phép toán hoặc toán hạng là loại mở rộng. Nếu giá trị là 0 thì loại thao tác hoặc toán hạng không phải là loại tiện ích mở rộng.

Để ánh xạ tiền tố tới tên tiện ích mở rộng, hãy tra cứu nó trong model.extensionNameToPrefix . Ánh xạ từ tiền tố đến tên mở rộng là sự tương ứng một-một (song song) 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 mở rộng trong các mô hình khác nhau.

Trình điều khiển phải xác thực các hoạt động mở rộng và loại dữ liệu vì thời gian chạy NNAPI không thể xác thực các hoạt động mở rộng và loại dữ liệu cụ thể.

Các toán hạng mở rộng có thể có dữ liệu liên quan trong operand.extraParams.extension mà thời gian chạy xử lý như một blob dữ liệu thô có kích thước tùy ý.

Hoạt động OEM và các loại dữ liệu

NNAPI có hoạt động OEM và các loại dữ liệu OEM để cho phép các nhà sản xuất thiết bị cung cấp chức năng tùy chỉnh, dành riêng cho trình điều khiển. Các loại hoạt động và dữ liệu này chỉ được sử dụng bởi các ứng dụng OEM. Ngữ nghĩa của hoạt động OEM và các loại dữ liệu là dành riêng cho OEM và có thể thay đổi bất kỳ lúc nào. Hoạt động OEM và các loại dữ liệu được mã hóa bằng cách sử dụng OperationType::OEM_OPERATION , OperandType::OEMOperandType::TENSOR_OEM_BYTE .