توضِّح هذه الصفحة هياكل البيانات والأساليب المستخدَمة في التواصل بفعالية مع مخازن الوسائط بين برنامج التشغيل والإطار.
في وقت تجميع النموذج، يقدّم الإطار القيم للمعاملات الثابتة إلى برنامج التشغيل. اعتمادًا على مدة بقاء المعامل الثابت، توجد قيمه إما في متجه HIDL أو في مجموعة ذاكرة مشتركة.
- إذا كانت الفترة الزمنية هي
CONSTANT_COPY
، تكون القيم متوفّرة في حقلoperandValues
في بنية النموذج. بما أنّه يتم نسخ القيم في ملف ملف تعريف HIDL أثناء عملية التواصل بين العمليات (IPC)، لا يتم استخدام هذا الملف عادةً إلا لتخزين كمية صغيرة من البيانات، مثل المعاملات السلاسل المتغيرة (على سبيل المثال، المعامل السلاسل المتغيرة للتنشيط فيADD
) ومَعلمات مصفوفات صغيرة (على سبيل المثال، مصفوفة الشكل فيRESHAPE
). - إذا كانت الفترة الزمنية هي
CONSTANT_REFERENCE
، تكون القيم متوفّرة في حقلpools
في بنية النموذج. يتم تكرار مقابض مجموعات الذاكرة المشتركة فقط أثناء IPC بدلاً من نسخ القيم الأولية. لذلك، من الأفضل الاحتفاظ بكمية كبيرة من البيانات (مثل مَعلمات الوزن في عمليات التفاف البيانات) باستخدام مجموعات الذاكرة المشتركة بدلاً من HIDL المتجهات.
في وقت تنفيذ النموذج، يقدّم إطار العمل وحدات التخزين المؤقتة لمعاملات الإدخال والإخراج إلى برنامج التشغيل. على عكس الثوابت في وقت الترجمة التي قد يتم إرسالها في مصفوفة HIDL، يتم دائمًا إرسال بيانات الإدخال والإخراج لعملية التنفيذ من خلال مجموعة من مجموعات الذاكرة.
يتم استخدام نوع بيانات HIDL hidl_memory
في كلّ من عملية الترجمة والتنفيذ لتمثيل مجموعة ذاكرة مشترَكة غير مُحدَّدة. يجب أن يربط برنامج التشغيل الذاكرة
وفقًا لذلك لجعلها قابلة للاستخدام استنادًا إلى اسم نوع البيانات hidl_memory
.
أسماء الذاكرة المتوافقة هي:
ashmem
: ذاكرة Android المشتركة لمزيد من التفاصيل، يُرجى الاطّلاع على الذاكرة.mmap_fd
: ذاكرة مشترَكة مستندة إلى ملف وصف من خلالmmap
-
hardware_buffer_blob
: ذاكرة مشترَكة مستندة إلى AHardwareBuffer بالتنسيقAHARDWARE_BUFFER_FORMAT_BLOB
متاح من Neural Networks (NN) HAL 1.2. لمعرفة مزيد من التفاصيل، يُرجى الاطّلاع على ADEVICEBuffer. -
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
. مع تجميع كل معلومات الأبعاد معًا،
قد يكون للمخزن المؤقت أبعاد أو ترتيب غير معروف. وفي هذه الحالة، يكون المورد الاحتياطي في حالة مرنة حيث تكون الأبعاد ثابتة عند استخدامها كإدخال نموذج وفي حالة ديناميكية عند استخدامه كمخرجات نموذج. يمكن استخدام ملف التخزين المؤقت نفسه بأشكال مختلفة من النتائج في عمليات التنفيذ المختلفة، ويجب أن يتعامل برنامج التشغيل مع إعادة ضبط حجم ملف التخزين المؤقت بشكل صحيح.
نطاق الذاكرة ميزة اختيارية. يمكن للسائق تحديد أنّه لا يمكنه تلبية طلب تخصيص معيّن لعدد من الأسباب. مثلاً:
- ذاكرة التخزين المؤقت المطلوبة لها حجم ديناميكي.
- يواجه برنامج تشغيل الجهاز قيودًا في الذاكرة تمنع استخدامه لمخازن مؤقتة كبيرة.
من الممكن أن تقرأ عدة سلاسل محادثات مختلفة من ملف التخزين المؤقت الذي يديره برنامج التشغيل بشكل متزامن. لا يمكن تحديد ما إذا كان الوصول إلى المخزن المؤقت في وقت واحد للكتابة أو القراءة/الكتابة يؤدي إلى حدوث خطأ، ولكن يجب ألّا يؤدي ذلك إلى تعطُّل خدمة برنامج التشغيل أو حظر المُتصل بشكلٍ دائم. يمكن أن يعرض برنامج التشغيل خطأ أو يترك محتوى المخزن المؤقت في حالة غير محددة.