توضِّح هذه الصفحة هياكل البيانات والأساليب المستخدَمة في التواصل بفعالية مع مخازن الوسائط بين برنامج التشغيل والإطار.
في وقت تجميع النموذج، يقدّم الإطار القيم للمعاملات الثابتة إلى برنامج التشغيل. استنادًا إلى مدة صلاحية المُشغِّل الثابت، يتم العثور على قيمه إما في متجه HIDL أو في مجموعة ذاكرة مشترَكة.
- إذا كانت الفترة الزمنية هي
CONSTANT_COPY
، تكون القيم متوفّرة في حقلoperandValues
في بنية النموذج. بما أنّه يتم نسخ القيم في ملف ملف تعريف HIDL أثناء عملية التواصل بين العمليات (IPC)، لا يتم استخدام هذا الملف عادةً إلا لتخزين كمية صغيرة من البيانات، مثل المعاملات السلاسل المتجهه (على سبيل المثال، المعامل السلاسل المتجهه للتنشيط فيADD
) ومَعلمات مصفوفة صغيرة (على سبيل المثال، مصفوفة الشكل فيRESHAPE
). - إذا كانت الفترة الزمنية هي
CONSTANT_REFERENCE
، تكون القيم متوفّرة في حقلpools
في بنية النموذج. يتم تكرار عناصر تحكّم مجموعات ملف ذاكرة التخزين المؤقت المشترَكة فقط أثناء تنسيق IPC بدلاً من نسخ القيم الأولية. لذلك، من الأفضل الاحتفاظ بكمية كبيرة من البيانات (مثل مَعلمات الوزن في عمليات التفاف البيانات) باستخدام مجموعات الذاكرة المشتركة بدلاً من HIDL المتجهات.
في وقت تنفيذ النموذج، يقدّم إطار العمل وحدات التخزين المؤقتة لمَعلمات الإدخال والإخراج إلى برنامج التشغيل. على عكس الثوابت في وقت الترجمة التي يمكن أن يتم إرسالها في مصفوفة HIDL، يتم دائمًا إرسال بيانات الإدخال والإخراج لعملية التنفيذ من خلال مجموعة من مجموعات الذاكرة.
يتم استخدام نوع بيانات HIDL hidl_memory
في كلّ من عملية الترجمة والتنفيذ ل represent تمثيل حزمة ذاكرة مشترَكة غير مُحدَّدة. يجب أن يربط برنامج التشغيل الذاكرة
وفقًا لذلك لجعلها قابلة للاستخدام استنادًا إلى اسم نوع البيانات hidl_memory
.
أسماء الذاكرة المتوافقة هي:
ashmem
: ذاكرة Android المشتركة لمزيد من التفاصيل، يُرجى الاطّلاع على الذاكرة.mmap_fd
: ذاكرة مشترَكة مستندة إلى صفِّ وصف ملف من خلالmmap
-
hardware_buffer_blob
: ذاكرة مشترَكة مستندة إلى AHardwareBuffer بالتنسيقAHARDWARE_BUFFER_FORMAT_BLOB
متاح من Neural Networks (NN) HAL 1.2. لمزيد من التفاصيل، يُرجى الاطّلاع على AHardwareBuffer. -
hardware_buffer
: ذاكرة مشترَكة مستندة إلى AHardwareBuffer عام لا يستخدم التنسيقAHARDWARE_BUFFER_FORMAT_BLOB
لا يتوفّر وضع عدم استخدام BLOB التخزين المؤقت للأجهزة إلا في تنفيذ النماذج.يتوفّر من NN HAL 1.2. لمزيد من التفاصيل، يُرجى الاطّلاع على AHardwareBuffer.
اعتبارًا من الإصدار 1.3 من NN HAL، تتيح NNAPI نطاقات الذاكرة التي توفّر واجهات تخصيص للمخازن المؤقتة التي يديرها برنامج التشغيل. يمكن أيضًا استخدام ملفّات التخزين المؤقت التي يديرها برنامج التشغيل كمدخلات أو مخرجات للتنفيذ. لمزيد من التفاصيل، يُرجى الاطّلاع على نطاقات الذاكرة.
يجب أن تتيح برامج تشغيل NNAPI ربط أسماء الذاكرة ashmem
وmmap_fd
. اعتبارًا من
NN HAL 1.3، يجب أن تتيح برامج التشغيل أيضًا ربط hardware_buffer_blob
. إنّ توفير دعم
للوضع العام غير المخصّص لتنسيق BLOB hardware_buffer
ونطاقات الذاكرة هو أمر اختياري.
AHardwareBuffer
AHardwareBuffer هو نوع من الذاكرة المشتركة التي تُغلِّف
عمود Gralloc. في الإصدار
10 من Android، تتيح واجهة برمجة التطبيقات Neural Networks API (NNAPI) استخدام
AHardwareBuffer،
ما يسمح لبرنامج التشغيل بتنفيذ عمليات بدون نسخ البيانات، ما يؤدي إلى تحسين
الأداء واستهلاك الطاقة للتطبيقات. على سبيل المثال، يمكن لحزمة HAL
الكاميرا تمرير عناصر AHardwareBuffer إلى NNAPI لأعمال تعلُّم الآلة
باستخدام عناصر تحكّم AHardwareBuffer التي تم إنشاؤها من خلال واجهتَي برمجة التطبيقات NDK للكاميرا وNDK للوسائط. لمزيد من المعلومات، يُرجى الاطّلاع على
ANeuralNetworksMemory_createFromAHardwareBuffer
.
يتم تمرير عناصر AHardwareBuffer المستخدَمة في NNAPI إلى برنامج التشغيل من خلال بنية
hidl_memory
باسم hardware_buffer
أو hardware_buffer_blob
.
لا يمثّل hidl_memory
hardware_buffer_blob
سوى عناصر AHardwareBuffer
بتنسيق AHARDWAREBUFFER_FORMAT_BLOB
.
يتم ترميز المعلومات المطلوبة من إطار العمل في حقل hidl_handle
من البنية hidl_memory
. يُغلِّف الحقل hidl_handle
الحقل native_handle
،
الذي يُشفِّر جميع البيانات الوصفية المطلوبة حول AHardwareBuffer أو ملف تخزين Gralloc.
يجب أن يفكّ رمز حقل hidl_handle
المقدَّم بشكل صحيح ويدخل إلى
الذاكرة الموضّحة في hidl_handle
. عند getSupportedOperations_1_2
،
getSupportedOperations_1_1
، أوgetSupportedOperations
يتم استدعاء الطريقة، يجب أن يرصد برنامج التشغيل ما إذا كان بإمكانه فك ترميز
hidl_handle
المقدَّمة والوصول إلى الذاكرة الموضّحة فيhidl_handle
. يجب أن يتعذّر تجهيز النموذج
إذا لم يكن الحقل hidl_handle
المستخدَم لمَعلمة ثابتة
متوافقًا. يجب أن يتعطّل التنفيذ إذا كان حقل hidl_handle
المستخدَم في عامل حسابي
للإدخال أو الإخراج في التنفيذ غير متوافق. يُنصح
بأن يعرض برنامج التشغيل رمز الخطأ GENERAL_FAILURE
في حال تعذّر تحضير النموذج
أو تنفيذه.
نطاقات الذكريات
بالنسبة إلى الأجهزة التي تعمل بنظام التشغيل Android 11 أو الإصدارات الأحدث، تتوافق واجهة برمجة التطبيقات NNAPI مع نطاقات الذاكرة التي توفّر واجهات لموزّعي الذاكرة في ملفّات التخزين المؤقت التي يديرها السائق. يتيح ذلك تمرير ذاكرات الجهاز الأصلية في جميع عمليات التنفيذ، ومنع تكرار نسخ البيانات وتحويلها بين عمليات التنفيذ المتتالية على برنامج التشغيل نفسه. يوضّح الشكل 1 هذه العملية.
الشكل 1: تخزين تدفق البيانات باستخدام نطاقات الذاكرة
تهدف ميزة نطاق الذاكرة إلى مصفوفات الخلاصات التي تكون داخلية في الغالب للسائق ولا تحتاج إلى الوصول إليها بشكل متكرّر من جانب العميل. وتشمل أمثلة ملفّات الملفات هذه ملفات الحالة في نماذج التسلسل. بالنسبة إلى مصفوفات Tensor التي تحتاج إلى الوصول المتكرّر إلى وحدة المعالجة المركزية من جهة العميل، من الأفضل استخدام مجموعات ذاكرة مشترَكة.
لتفعيل ميزة نطاق الذاكرة، نفِّذ IDevice::allocate
للسماح للإطار بطلب تخصيص المخزن المؤقت الذي يديره برنامج التشغيل. أثناء عملية التوزيع، يقدّم إطار العمل السمات التالية وأنماط الاستخدام التالية للمساحة التخزينية المؤقتة:
BufferDesc
يصف السمات المطلوبة للوسيط.- يصف
BufferRole
نمط الاستخدام المحتمل للوسيط كمدخل أو مخرج لنموذج معدّ. يمكن تحديد أدوار متعددة أثناء تخصيص ملف التخزين المؤقت، ولا يمكن استخدام ملف التخزين المؤقت المخصّص إلا للأدوار المحدّدة.
ويكون المخزن المؤقت المخصّص داخليًا للسائق. يمكن لبرنامج تشغيل اختيار أي موقع ملف مؤقت
أو تنسيق بيانات. عند تخصيص المخزن المؤقت بنجاح،
يمكن لعميل برنامج التشغيل الإشارة إلى المخزن المؤقت أو التفاعل معه باستخدام
الرمز المميّز الذي تم إرجاعه أو عنصر IBuffer
.
يتم تقديم الرمز المميّز من IDevice::allocate
عند الإشارة إلى المخزن المؤقت على أنّه أحد عناصر
MemoryPool
في بنية تنفيذ
Request
. لمنع أي عملية من محاولة الوصول إلى المخزن المؤقت
المخصّص في عملية أخرى، يجب أن يطبّق برنامج التشغيل عملية التحقّق المناسبة عند كل
استخدام للمخزن المؤقت. على برنامج التشغيل التحقّق من أنّ استخدام المخزن المؤقت هو أحد أدوار
BufferRole
المقدَّمة أثناء التخصيص، ويجب أن يوقف التنفيذ
على الفور إذا كان الاستخدام غير قانوني.
يتم استخدام العنصر
IBuffer
لنسخ الذاكرة بشكل صريح. في حالات معيّنة، يجب أن يُنشئ العميل
للبرنامج الوسيط ذاكرة تخزين مؤقتة تديرها وحدة التحكّم من مجموعة ذاكرة مشترَكة
أو ينسخ الذاكرة التخزينية المؤقتة إلى مجموعة ذاكرة مشترَكة. تشمل أمثلة حالات الاستخدام ما يلي:
- إعداد مصفوفة الحالة
- تخزين النتائج المؤقتة
- التنفيذ الاحتياطي على وحدة المعالجة المركزية
لدعم حالات الاستخدام هذه، يجب أن ينفِّذ برنامج التشغيل
IBuffer::copyTo
و
IBuffer::copyFrom
مع ashmem
وmmap_fd
وhardware_buffer_blob
إذا كان يدعم منح مجال الذاكرة. من الخيارات أن يتيح برنامج التشغيل وضع عدم استخدام BLOB
hardware_buffer
.
أثناء تخصيص المخزن المؤقت، يمكن استنتاج سمات المخزن المؤقت من
عوامل التشغيل النموذجية المقابلة لجميع الأدوار المحدّدة بواسطة BufferRole
، وال
السمات المقدّمة في BufferDesc
. عند جمع كل المعلومات المتعلّقة بالسمات، قد يحتوي المخزن المؤقت على سمات أو ترتيب غير معروفَين. في مثل هذه الحالة، يكون المخزن المؤقت في حالة مرنة حيث تكون السمات ثابتة عند استخدامه
كإدخال نموذج وفي حالة ديناميكية عند استخدامه كإخراج نموذج. يمكن استخدام ملف التخزين المؤقت نفسه بأشكال مختلفة من النتائج في عمليات التنفيذ المختلفة، ويجب أن يتعامل برنامج التشغيل مع إعادة ضبط حجم ملف التخزين المؤقت بشكل صحيح.
نطاق الذاكرة هو ميزة اختيارية. يمكن للسائق تحديد أنّه لا يمكنه تلبية طلب تخصيص معيّن لعدد من الأسباب. مثلاً:
- ذاكرة التخزين المؤقت المطلوبة لها حجم ديناميكي.
- يواجه برنامج تشغيل الجهاز قيودًا في الذاكرة تمنع استخدامه لمخازن مؤقتة كبيرة.
من الممكن أن تقرأ عدة سلاسل محادثات مختلفة من ملف التخزين المؤقت الذي يديره برنامج التشغيل بشكل متزامن. لا يمكن تحديد ما إذا كان الوصول إلى المخزن المؤقت في الوقت نفسه للكتابة أو القراءة/الكتابة يؤدي إلى حدوث خطأ، ولكن يجب ألّا يؤدي ذلك إلى تعطُّل خدمة برنامج التشغيل أو حظر المُتصل بشكلٍ دائم. يمكن أن يعرض برنامج التشغيل خطأ أو يترك محتوى المخزن المؤقت في حالة غير محدّدة.