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

تم تقديم إضافات موردو واجهات برمجة التطبيقات للشبكات العصبية (NNAPI) في Android 10، وهي عبارة عن مجموعات من أنواع البيانات والعمليات التي يحددها المورد. بالنسبة إلى الأجهزة التي تعمل بالإصدار 1.2 من NN 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 API.

لمعرفة ما إذا كان الجهاز متوافقًا مع الإضافة، يمكنك استخدام 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 بادئة الإضافة وتمثل وحدات البت Model::ExtensionTypeEncoding::LOW_BITS_TYPE المنخفضة نوع الإضافة أو تشغيلها.

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

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

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

يمكن لمعاملات الإضافة أن تحتوي على بيانات مرتبطة في operand.extraParams.extension، والتي تتعامل معها بيئة التشغيل على أنّها كائن ثنائي كبير بيانات أولي بحجم عشوائي.

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

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