حمامات الذاكرة

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

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

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

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

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

  • ashmem : الذاكرة المشتركة للأندرويد. لمزيد من التفاصيل، انظر الذاكرة .
  • 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 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 إذا كان يدعم تخصيص مجال الذاكرة. من الاختياري أن يدعم برنامج التشغيل وضع غير BLOB hardware_buffer .

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

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

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

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