إضافات المورّدين

إضافات Neural Networks API (NNAPI) الخاصة بالمورّدين، والتي تم طرحها في الإصدار Android 10، هي مجموعات من العمليات وأنواع البيانات التي يحدّدها المورّد. على الأجهزة التي تعمل بالإصدار 1.2 من NN HAL أو إصدار أحدث، يمكن لبرامج التشغيل توفير عمليات مخصّصة مُسرَّعة بالأجهزة من خلال إتاحة إضافات المورّدين المقابلة. لا تُعدِّل إضافات المورّدين بشكل أفضل للعمليات الحالية.

توفّر إضافات المورّدين بديلاً أكثر تنظيماً لعمليات المصنّعين الأصليين للأجهزة وأنواع البيانات التي تم إيقافها نهائيًا في 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,
        },
    },
}

من بين 32 وحدة بت مستخدمة لتحديد الأنواع والعمليات، Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX وbits هي الامتداد البادئة والدنيا Model::ExtensionTypeEncoding::LOW_BITS_TYPE البت تمثل النوع أو العملية من الإضافة.

عند التعامل مع عملية أو نوع معامِل، يجب أن يتحقّق برنامج التشغيل من الإضافة. . إذا كانت بادئة الإضافة لها قيمة غير صفرية، يكون نوع العملية أو المعامل هو نوع إضافة. إذا كانت القيمة هي 0، فهذا يعني نوع العملية أو المعامل ليس من أنواع الإضافات.

لربط البادئة باسم إضافة، ابحث عنها في model.extensionNameToPrefix. إنّ عملية الربط من البادئة إلى اسم الإضافة هي تطابق ثنائي الاتجاه (تطابق ثنائي) لنموذج معيّن. قد تتطابق قيم البادئة المختلفة مع اسم الإضافة نفسه في نماذج مختلفة.

يجب أن يتحقق برنامج التشغيل من صحة عمليات الإضافات وأنواع البيانات نظرًا لأن واجهة برمجة التطبيقات NNAPI لا يمكن لبيئة التشغيل التحقّق من صحة عمليات إضافة وأنواع بيانات معيّنة.

يمكن أن تحتوي عناصر التوسيع على بيانات مرتبطة في operand.extraParams.extension، التي يتعامل معها وقت التشغيل كمجموعة بيانات أولية بحجم عشوائي.

أنواع البيانات وعمليات المصنّع الأصلي للجهاز

تضم NNAPI عملية للمصنّع الأصلي للجهاز وأنواع بيانات المصنّع الأصلي للجهاز للسماح الشركات المصنعة للأجهزة إلى توفير وظائف مخصصة خاصة بالسائق. هذه تشغيل وأنواع البيانات فقط من قبل تطبيقات المصنّع الأصلي للجهاز. إنّ دلالات operatio وأنواع البيانات الخاصة بمصنعي المعدّات الأصليين خاصة بهم ويمكن أن تتغيّر في أي وقت. يتم ترميز نوعَي بيانات الشركة المصنّعة للجهاز وأنواع البيانات باستخدام OperationType::OEM_OPERATION وOperandType::OEM وOperandType::TENSOR_OEM_BYTE.