إضافات Neural Networks API (NNAPI) الخاصة بالمورّدين، التي تم طرحها في الإصدار Android 10، هي مجموعات من العمليات وأنواع البيانات التي يحدّدها المورّد. على الأجهزة التي تعمل بإصدار 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.
للتحقّق مما إذا كان الجهاز متوافقًا مع إضافة، استخدِم رمز
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, ¶ms, 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
.
إنّ التعيين من البادئة إلى اسم الإضافة هو تطابق ثنائي الاتجاه
(تطابق ثنائي) لنموذج معيّن. قد تتطابق قيم البادئة المختلفة مع اسم التمديد نفسه في نماذج مختلفة.
على برنامج التشغيل التحقّق من عمليات الإضافة وأنواع البيانات لأنّ وقت تنفيذ NNAPI لا يمكنه التحقّق من عمليات الإضافة وأنواع البيانات المحدّدة.
يمكن أن تحتوي عناصر التوسيع على بيانات مرتبطة في
operand.extraParams.extension
،
التي يتعامل معها وقت التشغيل كمجموعة بيانات أولية بحجم عشوائي.
أنواع البيانات وعمليات المصنّعين الأصليّين للأجهزة
تتضمّن واجهة برمجة التطبيقات NNAPI عمليات المصنّعين الأصليين للأجهزة وأنواع بياناتهم للسماح
للصنّاع الأصليين للأجهزة بتوفير وظائف مخصّصة خاصة بالبرامج المشغّلة. ولا يتم استخدام
أنواع العمليات والبيانات هذه إلا من خلال تطبيقات المصنّعين الأصليّين للأجهزة. إنّ دلالات operatio
وأنواع البيانات الخاصة بمصنعي المعدّات الأصليين خاصة بهم ويمكن أن تتغيّر في أي وقت. يتم ترميز نوعَي بيانات
الشركة المصنّعة للجهاز وأنواع البيانات باستخدام OperationType::OEM_OPERATION
وOperandType::OEM
وOperandType::TENSOR_OEM_BYTE
.