Tiện ích của nhà cung cấp

Tiện ích của nhà cung cấp Neural Networks API (NNAPI), được ra mắt trong Android 10 tập hợp các kiểu dữ liệu và thao tác do nhà cung cấp xác định. Trên những thiết bị chạy NN HAL 1.2 trở lên, người lái xe có thể cung cấp các thao tác được tăng tốc phần cứng tuỳ chỉnh bằng cách hỗ trợ tiện ích tương ứng của nhà cung cấp. Tiện ích nhà cung cấp không sửa đổi hành vi của các hoạt động hiện tại.

Tiện ích của nhà cung cấp cung cấp giải pháp thay thế có cấu trúc hơn cho hoạt động của OEM và (không 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 của OEM.

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

Tiện ích của nhà cung cấp chỉ có thể được sử dụng bởi các ứng dụng Android được chỉ định rõ ràng và tệp nhị phân gốc trên 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 nhà cung cấp tiện ích.

Danh sách các ứng dụng Android và tệp nhị phân được phép sử dụng tiện ích của nhà cung cấp NNAPI là được lưu trữ trong /vendor/etc/nnapi_extensions_app_allowlist. Mỗi dòng của tệp có chứa một mục nhập 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 một gói ứng dụng Android, cho ví dụ: com.foo.bar.

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

Định nghĩa tiện ích của nhà cung cấp

Nhà cung cấp tạo và duy trì tệp tiêu đề có định nghĩa tiện ích. Đáp bạn có thể xem ví dụ hoàn chỉnh về định nghĩa tiện ích trong example/fibonacci/FibonacciExtension.h.

Mỗi tiện ích phải có một tên riêng biệ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 đóng vai trò là một không gian tên cho các thao tác và loại dữ liệu. NNAPI sử dụng để phân biệt các tiện ích của nhà cung cấp.

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,
};

Toán tử mở rộng có thể sử dụng bất kỳ loại toán hạng nào, bao gồm cả toán hạng không mở rộng loại và loại toán hạng từ các tiện ích khác. Khi sử dụng loại toán hạng từ một tiện ích khác, thì trình điều khiển phải hỗ trợ tiện ích đó.

Tiện ích cũng có thể khai báo cấu trúc tuỳ chỉnh đi kèm với 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 phần mở rộng trong các ứng dụng NNAPI

Chiến lược phát hành đĩa đơn runtime/include/NeuralNetworksExtensions.h Tệp (API C) hỗ trợ tiện ích thời gian chạy. Phần này cung cấp tổng quan về C API.

Để kiểm tra xem thiết bị có hỗ trợ tiện ích 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 bằng 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);

Sử dụng (không bắt buộc) 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 bằng thao tác mở rộng, hãy sử dụng ANeuralNetworksModel_getExtensionOperationType để biết loại tác vụ và gọi lệnh 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 một trình điều khiển NNAPI

Trình điều khiển báo cáo các tiện ích được hỗ trợ thông qua IDevice::getSupportedExtensions . Danh sách được trả về phải chứa mục nhập mô tả từng mục được hỗ trợ tiện ích.

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 dùng để xác định kiểu và hoạt động, Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX bit là phần mở rộng tiền tố và số tiền tố thấp Model::ExtensionTypeEncoding::LOW_BITS_TYPE bit biểu thị kiểu hoặc toán tử của tiện ích.

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

Để liên kết tiền tố với tên một tiện ích, hãy tra cứu tiền tố đó trong model.extensionNameToPrefix. Việc liên kết từ tiền tố đến tên tiện ích là sự tương ứng một với một (tham chiếu) cho một mô hình đã cho. 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 toán tử mở rộng và loại dữ liệu vì NNAPI thời gian chạy không thể xác thực các loại dữ liệu và thao tác mở rộng cụ thể.

Toán hạng mở rộng có thể có dữ liệu được liên kết trong operand.extraParams.extension! mà thời gian chạy sẽ coi là một blob dữ liệu thô có kích thước tùy ý.

Loại dữ liệu và hoạt động của OEM

NNAPI có một toán tử 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 người lái xe. Các loại dữ liệu và hoạt động chỉ được các ứng dụng OEM sử dụng. Ngữ nghĩa của OEM (Nhà sản xuất thiết bị gốc) loại dữ liệu và hoạt động cụ thể của OEM và có thể thay đổi bất cứ lúc nào. OEM (Nhà sản xuất thiết bị gốc) thao tác và loại dữ liệu được mã hoá bằng OperationType::OEM_OPERATION, OperandType::OEMOperandType::TENSOR_OEM_BYTE.