تجمعات الذاكرة

تصف هذه الصفحة هياكل البيانات والأساليب المستخدمة للتواصل بكفاءة مع المخازن المؤقتة للمعامل بين السائق وإطار العمل.

في وقت تجميع النموذج ، يوفر الإطار قيم المعاملات الثابتة للسائق. اعتمادًا على عمر المعامل الثابت ، توجد قيمه إما في متجه HIDL أو في تجمع ذاكرة مشتركة.

  • إذا كان العمر هو CONSTANT_COPY ، فستكون القيم موجودة في حقل operandValues في بنية النموذج. نظرًا لأن القيم الموجودة في متجه HIDL يتم نسخها أثناء الاتصال بين العمليات (IPC) ، يتم استخدام هذا عادةً فقط للاحتفاظ بكمية صغيرة من البيانات مثل المعاملات العددية (على سبيل المثال ، عدد التنشيط في ADD ) ومعلمات موتر صغيرة (على سبيل المثال ، موتر الشكل في RESHAPE ).
  • إذا كان العمر هو CONSTANT_REFERENCE ، فستكون القيم موجودة في حقل pools لبنية النموذج. يتم تكرار مقابض تجمعات الذاكرة المشتركة فقط أثناء IPC بدلاً من نسخ القيم الأولية. لذلك ، من الأفضل الاحتفاظ بكمية كبيرة من البيانات (على سبيل المثال ، معلمات الوزن في التلافيف) باستخدام تجمعات الذاكرة المشتركة من متجهات HIDL.

في وقت تنفيذ النموذج ، يوفر الإطار المخازن المؤقتة لمعاملات الإدخال والإخراج للسائق. على عكس ثوابت وقت الترجمة التي قد يتم إرسالها في متجه HIDL ، يتم دائمًا توصيل بيانات الإدخال والإخراج للتنفيذ من خلال مجموعة من تجمعات الذاكرة.

يتم استخدام نوع بيانات hidl_memory في كل من التحويل البرمجي والتنفيذ لتمثيل تجمع ذاكرة مشتركة غير معين. يجب على برنامج التشغيل تعيين الذاكرة وفقًا لذلك لجعلها قابلة للاستخدام بناءً على اسم نوع بيانات hidl_memory . أسماء الذاكرة المدعومة هي:

  • ashmem : ذاكرة Android مشتركة. لمزيد من التفاصيل ، انظر الذاكرة .
  • mmap_fd : الذاكرة المشتركة مدعومة بواصف ملف من خلال mmap .
  • hardware_buffer_blob : ذاكرة مشتركة مدعومة بواسطة AHardwareBuffer بالتنسيق AHARDWARE_BUFFER_FORMAT_BLOB . متاح من الشبكات العصبية (NN) HAL 1.2. لمزيد من التفاصيل ، راجع AHardwareBuffer .
  • hardware_buffer : ذاكرة مشتركة مدعومة بواسطة AHardwareBuffer عام لا يستخدم التنسيق AHARDWARE_BUFFER_FORMAT_BLOB . يتم دعم المخزن المؤقت للأجهزة الذي لا يحتوي على وضع BLOB فقط في تنفيذ النموذج ، وهو متاح من NN HAL 1.2. لمزيد من التفاصيل ، راجع AHardwareBuffer .

من NN HAL 1.3 ، يدعم NNAPI مجالات الذاكرة التي توفر واجهات مخصصة للمخازن المؤقتة التي يديرها برنامج التشغيل. يمكن أيضًا استخدام المخازن المؤقتة التي يديرها برنامج التشغيل كمدخلات أو مخرجات تنفيذية. لمزيد من التفاصيل ، راجع مجالات الذاكرة .

يجب أن تدعم برامج تشغيل NNAPI تعيين أسماء الذاكرة ashmem و mmap_fd . من NN HAL 1.3 ، يجب أن تدعم برامج التشغيل أيضًا تعيين hardware_buffer_blob . دعم النطاقات العامة لمخزن hardware_buffer والذاكرة غير الموجودة في وضع كائن تخزين البيانات الثنائية الكبيرة (BLOB) اختياري.

AHardwareBuffer

AHardwareBuffer هو نوع من الذاكرة المشتركة التي تغلف مخزن Gralloc المؤقت . في Android 10 ، تدعم واجهة برمجة تطبيقات الشبكات العصبية (NNAPI) استخدام AHardwareBuffer ، مما يسمح للسائق بتنفيذ عمليات التنفيذ دون نسخ البيانات ، مما يحسن الأداء واستهلاك الطاقة للتطبيقات. على سبيل المثال ، يمكن لمكدس HAL للكاميرا تمرير كائنات AHardwareBuffer إلى NNAPI لأحمال عمل التعلم الآلي باستخدام مقابض AHardwareBuffer التي تم إنشاؤها بواسطة NDK للكاميرا وواجهات برمجة تطبيقات الوسائط NDK. لمزيد من المعلومات ، راجع ANeuralNetworksMemory_createFromAHardwareBuffer .

يتم تمرير كائنات AHardwareBuffer المستخدمة في NNAPI إلى برنامج التشغيل من خلال بنية hidl_memory تسمى إما hardware_buffer أو hardware_buffer_blob . يمثل hidl_memory architecture hardware_buffer_blob كائنات AHardwareBuffer فقط بتنسيق AHARDWAREBUFFER_FORMAT_BLOB .

يتم ترميز المعلومات المطلوبة بواسطة إطار العمل في حقل hidl_handle الخاص hidl_memory . يلف الحقل hidl_handle native_handle ، والذي يشفر جميع البيانات الوصفية المطلوبة حول AHardwareBuffer أو Gralloc buffer.

يجب على السائق فك شفرة حقل 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. تدفق البيانات العازلة باستخدام مجالات الذاكرة

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

لدعم ميزة مجال الذاكرة ، قم بتنفيذ IDevice::allocate للسماح لإطار العمل بطلب تخصيص المخزن المؤقت الذي يديره برنامج التشغيل. أثناء التخصيص ، يوفر إطار العمل الخصائص وأنماط الاستخدام التالية للمخزن المؤقت:

  • يصف BufferDesc الخصائص المطلوبة للمخزن المؤقت.
  • يصف BufferRole نمط الاستخدام المحتمل للمخزن المؤقت كمدخل أو إخراج لنموذج مُعد. يمكن تحديد أدوار متعددة أثناء تخصيص المخزن المؤقت ، ويمكن استخدام المخزن المؤقت المخصص فقط كتلك الأدوار المحددة.

المخزن المؤقت المخصص داخلي للسائق. يمكن للسائق اختيار أي موقع مخزن مؤقت أو تخطيط بيانات. عند تخصيص المخزن المؤقت بنجاح ، يمكن للعميل الخاص ببرنامج التشغيل الرجوع إلى المخزن المؤقت أو التفاعل معه باستخدام الرمز المميز الذي تم إرجاعه أو كائن IBuffer .

يتم توفير الرمز المميز من IDevice::allocate عند الرجوع إلى المخزن المؤقت كأحد كائنات MemoryPool في بنية Request للتنفيذ. لمنع عملية من محاولة الوصول إلى المخزن المؤقت المخصص في عملية أخرى ، يجب على برنامج التشغيل تطبيق التحقق المناسب من الصحة عند كل استخدام للمخزن المؤقت. يجب أن يتحقق برنامج التشغيل من أن استخدام المخزن المؤقت هو أحد أدوار BufferRole المتوفرة أثناء التخصيص ويجب أن يفشل في التنفيذ فورًا إذا كان الاستخدام غير قانوني.

يتم استخدام كائن IBuffer للنسخ الصريح للذاكرة. في حالات معينة ، يجب على عميل برنامج التشغيل تهيئة المخزن المؤقت المُدار بواسطة برنامج التشغيل من تجمع ذاكرة مشتركة أو نسخ المخزن المؤقت إلى تجمع ذاكرة مشتركة. تشمل أمثلة حالات الاستخدام ما يلي:

  • تهيئة موتر الدولة
  • تخزين النتائج الوسيطة
  • التنفيذ الاحتياطي على وحدة المعالجة المركزية

لدعم حالات الاستخدام هذه ، يجب أن يقوم برنامج التشغيل بتطبيق IBuffer::copyTo و IBuffer::copyFrom مع ashmem و mmap_fd و hardware_buffer_blob إذا كان يدعم تخصيص مجال الذاكرة. إنه اختياري لبرنامج التشغيل لدعم hardware_buffer غير الموجودة في وضع BLOB.

أثناء تخصيص المخزن المؤقت ، يمكن استنتاج أبعاد المخزن المؤقت من معاملات النموذج المقابلة لجميع الأدوار المحددة بواسطة BufferRole والأبعاد المتوفرة في BufferDesc . مع تجميع جميع معلومات الأبعاد ، قد يكون للمخزن المؤقت أبعاد أو ترتيب غير معروف. في مثل هذه الحالة ، يكون المخزن المؤقت في حالة مرنة حيث يتم إصلاح الأبعاد عند استخدامها كمدخل نموذج وفي حالة ديناميكية عند استخدامها كمخرجات نموذج. يمكن استخدام نفس المخزن المؤقت مع أشكال مختلفة من المخرجات في عمليات تنفيذ مختلفة ويجب على السائق التعامل مع تغيير حجم المخزن المؤقت بشكل صحيح.

مجال الذاكرة هو ميزة اختيارية. يمكن للسائق تحديد أنه لا يمكنه دعم طلب تخصيص معين لعدد من الأسباب. فمثلا:

  • المخزن المؤقت المطلوب له حجم ديناميكي.
  • السائق لديه قيود في الذاكرة تمنعه ​​من التعامل مع المخازن المؤقتة الكبيرة.

من الممكن أن تقرأ عدة مؤشرات ترابط مختلفة من المخزن المؤقت الذي يديره برنامج التشغيل بشكل متزامن. الوصول إلى المخزن المؤقت في وقت واحد للكتابة أو القراءة / الكتابة غير محدد ، ولكن يجب ألا يؤدي إلى تعطيل خدمة السائق أو حظر المتصل إلى أجل غير مسمى. يمكن لبرنامج التشغيل إرجاع خطأ أو ترك محتوى المخزن المؤقت في حالة غير محددة.