Ekstensi vendor

Ekstensi vendor Neural Networks API (NNAPI), yang diperkenalkan di Android 10, adalah kumpulan operasi dan tipe data yang ditentukan vendor. Pada perangkat yang menjalankan NN HAL 1.2 atau lebih tinggi, driver dapat menyediakan operasi akselerasi perangkat keras khusus dengan mendukung ekstensi vendor yang sesuai. Ekstensi vendor tidak mengubah perilaku operasi yang ada.

Ekstensi vendor memberikan alternatif yang lebih terstruktur terhadap operasi dan tipe data OEM, yang tidak digunakan lagi di Android 10. Untuk informasi selengkapnya, lihat Operasi dan tipe data OEM .

Daftar penggunaan ekstensi yang diizinkan

Ekstensi vendor hanya dapat digunakan oleh aplikasi Android dan biner asli yang ditentukan secara eksplisit pada partisi /product , /vendor , /odm , dan /data . Aplikasi dan biner asli yang terletak di partisi /system tidak dapat menggunakan ekstensi vendor.

Daftar aplikasi dan binari Android yang diizinkan menggunakan ekstensi vendor NNAPI disimpan di /vendor/etc/nnapi_extensions_app_allowlist . Setiap baris file berisi entri baru. Entri dapat berupa jalur biner asli yang diawali dengan garis miring (/), misalnya /data/foo , atau nama paket aplikasi Android, misalnya com.foo.bar .

Daftar yang diizinkan diterapkan dari pustaka bersama waktu proses NNAPI. Pustaka ini melindungi terhadap penggunaan yang tidak disengaja namun tidak terhadap pengelakan yang disengaja oleh aplikasi secara langsung menggunakan antarmuka HAL driver NNAPI.

Definisi ekstensi vendor

Vendor membuat dan memelihara file header dengan definisi ekstensi. Contoh lengkap definisi ekstensi dapat ditemukan di example/fibonacci/FibonacciExtension.h .

Setiap ekstensi harus memiliki nama unik yang dimulai dengan nama domain kebalikan dari vendor.

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

Nama bertindak sebagai namespace untuk operasi dan tipe data. NNAPI menggunakan nama ini untuk membedakan antara ekstensi vendor.

Operasi dan tipe data dideklarasikan dengan cara yang mirip dengan 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,
};

Operasi ekstensi dapat menggunakan tipe operan apa pun, termasuk tipe operan non-ekstensi dan tipe operan dari ekstensi lain. Saat menggunakan jenis operan dari ekstensi lain, driver harus mendukung ekstensi lainnya.

Ekstensi juga dapat mendeklarasikan struktur khusus untuk menyertai operan ekstensi.

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

Gunakan ekstensi di klien NNAPI

File runtime/include/NeuralNetworksExtensions.h (C API) menyediakan dukungan ekstensi runtime. Bagian ini memberikan gambaran umum tentang C API.

Untuk memeriksa apakah perangkat mendukung ekstensi, gunakan ANeuralNetworksDevice_getExtensionSupport .

bool isExtensionSupported;
CHECK_EQ(ANeuralNetworksDevice_getExtensionSupport(device, EXAMPLE_EXTENSION_NAME,
                                                   &isExtensionSupported),
         ANEURALNETWORKS_NO_ERROR);
if (isExtensionSupported) {
    // The device supports the extension.
    ...
}

Untuk membangun model dengan operan ekstensi, gunakan ANeuralNetworksModel_getExtensionOperandType untuk mendapatkan jenis operan dan panggil 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);

Secara opsional, gunakan ANeuralNetworksModel_setOperandExtensionData untuk mengaitkan data tambahan dengan operan ekstensi.

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

Untuk membangun model dengan operasi ekstensi, gunakan ANeuralNetworksModel_getExtensionOperationType untuk mendapatkan jenis operasi dan memanggil 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);

Tambahkan dukungan ekstensi ke driver NNAPI

Driver melaporkan ekstensi yang didukung melalui metode IDevice::getSupportedExtensions . Daftar yang dikembalikan harus berisi entri yang menjelaskan setiap ekstensi yang didukung.

Extension {
    .name = EXAMPLE_EXTENSION_NAME,
    .operandTypes = {
        {
            .type = EXAMPLE_SCALAR,
            .isTensor = false,
            .byteSize = 8,
        },
        {
            .type = EXAMPLE_TENSOR,
            .isTensor = true,
            .byteSize = 8,
        },
    },
}

Dari 32 bit yang digunakan untuk mengidentifikasi jenis dan operasi, bit Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX yang tinggi adalah awalan ekstensi dan bit Model::ExtensionTypeEncoding::LOW_BITS_TYPE yang rendah mewakili jenis atau pengoperasian ekstensi.

Saat menangani suatu operasi atau jenis operan, pengemudi harus memeriksa awalan ekstensi. Jika awalan ekstensi memiliki nilai bukan nol, jenis operasi atau operan adalah jenis ekstensi. Jika nilainya 0 , jenis operasi atau operan bukan merupakan jenis ekstensi.

Untuk memetakan awalan ke nama ekstensi, cari di model.extensionNameToPrefix . Pemetaan dari awalan ke nama ekstensi merupakan korespondensi satu-satu (bijection) untuk model tertentu. Nilai awalan yang berbeda mungkin berhubungan dengan nama ekstensi yang sama di model yang berbeda.

Pengemudi harus memvalidasi operasi ekstensi dan tipe data karena runtime NNAPI tidak dapat memvalidasi operasi ekstensi dan tipe data tertentu.

Operan ekstensi dapat memiliki data terkait di operand.extraParams.extension , yang diperlakukan oleh runtime sebagai gumpalan data mentah dengan ukuran sewenang-wenang.

Operasi OEM dan tipe data

NNAPI memiliki operasi OEM dan tipe data OEM untuk memungkinkan produsen perangkat menyediakan fungsionalitas khusus driver khusus. Operasi dan tipe data ini hanya digunakan oleh aplikasi OEM. Semantik operasi OEM dan tipe data bersifat spesifik OEM dan dapat berubah kapan saja. Operasi OEM dan tipe data dikodekan menggunakan OperationType::OEM_OPERATION , OperandType::OEM , dan OperandType::TENSOR_OEM_BYTE .