افزونه‌های فروشنده

افزونه‌های فروشنده «میانای برنامه‌سازی کاربردی شبکه عصبی» (NNAPI) که در Android 10 معرفی شده‌اند، مجموعه‌هایی از عملیات و انواع داده‌های تعریف‌شده توسط فروشنده هستند. در دستگاه‌هایی که HAL 1.2 یا بالاتر را اجرا می‌کنند، درایورها می‌توانند با پشتیبانی از افزونه‌های فروشنده مربوطه، عملیات شتاب‌دار سخت‌افزاری سفارشی ارائه دهند. افزونه‌های فروشنده رفتار عملیات‌های موجود را تغییر نمی‌دهند.

افزونه‌های فروشنده جایگزین ساختاریافته‌تری برای عملکرد سازنده اصلی محصول و انواع داده ارائه می‌دهند که در Android 10 منسوخ شده‌اند. برای کسب اطلاعات بیشتر، به عملکرد سازنده تجهیزات اصلی و انواع داده مراجعه کنید.

فهرست مجاز استفاده از افزونه‌ها

افزونه‌های فروشنده فقط توسط برنامه‌های Android مشخص‌شده به‌طور صریح و دودویی‌های بومی در بخش‌های /product، /vendor، /odm، و /data قابل‌استفاده است. برنامه‌ها و باینری‌های بومی موجود در پارتیشن /system نمی‌توانند از افزونه‌های فروشنده استفاده کنند.

فهرستی از برنامه‌ها و دودویی‌های Android که مجاز به استفاده از افزونه‌های تأمین‌کننده NNAPI هستند در /vendor/etc/nnapi_extensions_app_allowlist ذخیره شده است. هر خط فایل حاوی ورودی جدیدی است. ورودی می‌تواند مسیر دودویی بومی باشد که با خط مورب (/) پیشوندگذاری شده است، برای مثال، /data/foo، یا نام بسته برنامه Android، برای مثال، com.foo.bar.

فهرست مجاز از کتابخانه مشترک زمان اجرای NNAPI اعمال می‌شود. این کتابخانه از استفاده تصادفی محافظت می‌کند اما از دور زدن عمدی توسط برنامه‌ای که مستقیماً از میانای HAL درایور NNAPI استفاده می‌کند محافظت نمی‌کند.

تعریف افزونه فروشنده

فروشنده یک فایل سرایند با تعریف افزونه ایجاد و نگهداری می‌کند. نمونه کامل تعریف افزونه را می‌توانید در 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» ارائه می‌دهد.

برای بررسی اینکه آیا دستگاهی از افزونه‌ای پشتیبانی می‌کند یا نه، از 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, &params, 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,
        },
    },
}

از ۳۲ بیت استفاده‌شده برای شناسایی انواع و عملیات، بیت‌های بالا Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX پیشوند افزونه و بیت‌های پایین Model::ExtensionTypeEncoding::LOW_BITS_TYPE نوع یا عملیات افزونه را نشان می‌دهد.

هنگام مدیریت عملیات یا نوع عملوند، درایور باید پیشوند افزونه را بررسی کند. اگر پیشوند افزونه مقدار غیرصفر داشته باشد، نوع عملیات یا عملوند از نوع افزونه است. اگر مقدار 0 باشد، نوع عملگر یا عملوند نوع افزونه نیست.

برای نگاشت پیشوند به نام افزونه، آن را در model.extensionNameToPrefix جستجو کنید. نگاشت از پیشوند به نام افزونه برای مدل معینی یک‌به‌یک است (دوسویی). مقادیر پیشوند متفاوت ممکن است با نام افزونه یکسان در مدل‌های مختلف مطابقت داشته باشد.

درایور باید عملیات افزونه و انواع داده را اعتبارسنجی کند زیرا زمان اجرای NNAPI نمی‌تواند عملیات افزونه و انواع داده خاصی را اعتبارسنجی کند.

عملوندهای افزونه می‌توانند داده‌های مرتبط در operand.extraParams.extension داشته باشند، که زمان اجرا آن را به‌عنوان یک حباب داده خام با اندازه دلخواه درنظر می‌گیرد.

انواع داده و عملکرد سازنده تجهیزات اصلی

NNAPI دارای عملیات OEM و انواع داده OEM است تا به سازندگان دستگاه اجازه دهد عملکرد سفارشی و مختص درایور ارائه دهند. این انواع عملیات و داده‌ها فقط توسط برنامه‌های OEM استفاده می‌شود. معناشناسی عملیات و انواع داده‌های OEM مختص OEM است و می‌تواند در هر زمانی تغییر کند. عملکرد OEM و انواع داده بااستفاده از OperationType::OEM_OPERATION، OperandType::OEM، و OperandType::TENSOR_OEM_BYTE کدبندی می‌شوند.