يقدّم Neural Networks HAL 1.2 مفهوم عمليات التنفيذ المفاجئة. عمليات تنفيذ المعالجة المكثّفة هي تسلسل عمليات تنفيذ النموذج المعدّ نفسه التي تحدث في تتابع سريع، مثل تلك التي تعمل على لقطات من الكاميرا أو نماذج صوتية متتالية. يُستخدم كائن الصور المتسلسلة للتحكم في مجموعة من عمليات تنفيذ الصور المتسلسلة، وللحفاظ على الموارد بين عمليات التنفيذ، ما يتيح لعمليات التنفيذ خفض النفقات العامة. تتيح لك ميزة "التقاط الصور المتسلسلة" إجراء ثلاثة تحسينات:
- يتم إنشاء عنصر معالجة مكثّفة قبل تسلسل عمليات التنفيذ، ويتم تحريره عند انتهاء التسلسل. ولهذا السبب، يشير تاريخ بقاء كائن الصور المتسلسلة إلى برنامج التشغيل إلى المدة التي يجب أن يظل فيها في حالة الأداء العالي.
- يمكن لكائن الصور المتسلسلة الاحتفاظ بالموارد بين عمليات التنفيذ. على سبيل المثال، يمكن لبرنامج التشغيل ربط كائن ذاكرة عند التنفيذ الأول وتخزينه مؤقتًا في كائن الصور المتسلسلة لإعادة استخدامه في عمليات التنفيذ اللاحقة. ويمكن تحرير أي مورد مخزَّن مؤقتًا عند إتلاف كائن الصور المتسلسلة أو عندما يُبلغ وقت تشغيل NNAPI الكائن المتسلسلة بأن المورد لم يعد مطلوبًا.
- يستخدم كائن الصور المتسلسلة قوائم انتظار الرسائل السريعة (FMQs) للتواصل بين عمليات التطبيق وبرامج التشغيل. وقد يؤدي ذلك إلى تقليل وقت الاستجابة لأن FMQ تتخطى HIDL وتمرر البيانات مباشرةً إلى عملية أخرى من خلال نظام FIFO دائري صغير في الذاكرة المشتركة. يُطلَب من عملية المستهلك إزالة المنتج من قائمة الانتظار وبدء المعالجة إما من خلال استطلاع عدد العناصر في معيار FIFO أو انتظار علامة الفعالية FMQ التي أشار إليها المنتج. علامة الحدث هذه هي قفل ملف ثنائي سريع في مساحة المستخدم (futex).
آلية FMQ هي بنية بيانات منخفضة المستوى لا توفّر أي ضمانات دائمة في جميع العمليات ولا تحتوي على آلية مدمجة لتحديد ما إذا كانت العملية في الطرف الآخر من FMQ تعمل على النحو المتوقع. نتيجةً لذلك، إذا توقّف مُنتج البيانات الوصفية الثابتة عن العمل، قد ينتظر المستهلك وصول البيانات التي لا تصل أبدًا. يتمثّل أحد الحلول لهذه المشكلة في أن يربط برنامج التشغيل FMQs بكائن الصور المتسلسلة ذات المستوى الأعلى لرصد وقت انتهاء تنفيذ الصور المتسلسلة.
نظرًا لأن عمليات تنفيذ الصور المتسلسلة تعمل على نفس الوسيطات وتعرض النتائج نفسها مثل مسارات التنفيذ الأخرى، يجب أن تمرر FMQs الأساسية البيانات نفسها من وإلى برامج تشغيل خدمة NNAPI. ومع ذلك، لا يمكن لواجهات FMQ نقل سوى
أنواع البيانات القديمة. يتم نقل البيانات المعقدة من خلال تسلسل
وإلغاء تسلسل المخزن المؤقت المتداخل (أنواع المتجهات) مباشرةً في قوائم الانتظار للطلبات القصيرة (FMQ)، واستخدام
عناصر طلب استدعاء HIDL لنقل عناصر ذاكرة التخزين المؤقت عند الطلب. يجب أن يرسل جانب المنتج من FMQ رسائل الطلب أو النتائج إلى المستهلك بشكل كامل باستخدام MessageQueue::writeBlocking
إذا كانت قائمة الانتظار محظورة، أو باستخدام MessageQueue::write
إذا كانت قائمة الانتظار غير محظورة.
واجهات الصور المتسلسلة
يمكن العثور على واجهات الصور المتسلسلة في HAL للشبكات العصبية في hardware/interfaces/neuralnetworks/1.2/
، وهي موضّحة أدناه. لمزيد من المعلومات عن واجهات التصوير المتسلسل في Ndk
layer، يُرجى الاطّلاع على frameworks/ml/nn/runtime/include/NeuralNetworks.h
.
types.hal
types.hal
يحدِّد نوع البيانات التي يتم إرسالها عبر FMQ.
-
FmqRequestDatum
: عنصر واحد لتمثيل تسلسلي لشيء تنفيذRequest
وقيمتهMeasureTiming
، ويتم إرساله عبر قائمة انتظار الرسائل السريعة . FmqResultDatum
: هو عنصر واحد لعرض متسلسل للقيم الناتجة عن عملية تنفيذ (ErrorStatus
وOutputShapes
وTiming
)، ويتم عرضه من خلال قائمة انتظار الرسائل السريعة.
IBurstContext.hal
IBurstContext.hal
يحدِّد عنصر واجهة HIDL الذي يتوفّر في خدمة الشبكات العصبية.
IBurstContext
: كائن سياق لإدارة موارد الصور المتسلسلة.
IBurstCallback.hal
IBurstCallback.hal
يحدِّد عنصر واجهة HIDL لمكالمة إعادة الاتصال التي أنشأها وقت تنفيذ Neural Networks
، وتستخدمها خدمة Neural Networks لاسترداد عناصر hidl_memory
المتوافقة مع معرّفات الفتحات.
- IBurstCallback: عنصر استدعاء تستخدمه الخدمة لاسترداد عناصر الذاكرة.
IPreparedModel.hal
تم توسعة IPreparedModel.hal
في HAL 1.2 من خلال طريقة لإنشاء عنصر IBurstContext
من
نموذج مُعدّ.
-
configureExecutionBurst
: يضبط عنصرًا متسلسلًا يُستخدَم لتنفيذ استنتاجات متعدّدة على نموذج مُعدّ بشكل متتابع سريع.
إتاحة عمليات التنفيذ المكثّفة في برنامج تشغيل
إنّ أبسط طريقة لدعم العناصر المتسلسلة في خدمة HIDL NNAPI هي استخدام
دالة الأدوات المتسلسلة ::android::nn::ExecutionBurstServer::create
،
الموجودة في
ExecutionBurstServer.h
والمجمّعة في المكتبتين libneuralnetworks_common
وlibneuralnetworks_util
الثابتة. تحتوي دالة المصنع هذه على تحميل زائدَين:
- يقبل أحد أساليب التحميل الزائد مؤشرًا إلى عنصر
IPreparedModel
. تستخدم دالة المرافق هذه الطريقةexecuteSynchronously
في عنصرIPreparedModel
لتنفيذ النموذج. - يقبل أحد أساليب التحميل الزائد عنصر
IBurstExecutorWithCache
قابل للتخصيص، يمكن استخدامه لتخزين الموارد مؤقتًا (مثل عمليات ربطhidl_memory
) التي تظل محفوظة على مدار عمليات تنفيذ متعددة.
تعرض كل طريقة تحميل زائدة عنصر IBurstContext
(الذي يمثّل عنصر
الدفعة) الذي يحتوي على سلسلة محادثات مستمع مخصّصة ويديرها. تتلقّى سلسلة المحادثات هذه الطلبات من requestChannel
FMQ، وتجري الاستنتاج، ثم تعرض النتائج من خلال resultChannel
FMQ. يتم تلقائيًا تحرير سلسلة المحادثات هذه وجميع موارد
الأخرى المضمّنة في عنصر IBurstContext
عندما يفقد عميل البث المفاجئ مرجعه إلى IBurstContext
.
يمكنك بدلاً من ذلك إنشاء طريقة تنفيذ خاصة بك لـ IBurstContext
الذي
يفهم كيفية إرسال الرسائل واستلامها باستخدام requestChannel
و
resultChannel
FMQ التي تم تمريرها إلى IPreparedModel::configureExecutionBurst
.
يمكن العثور على وظائف الصور المتسلسلة في ExecutionBurstServer.h
.
/**
* Create automated context to manage FMQ-based executions.
*
* This function is intended to be used by a service to automatically:
* 1) Receive data from a provided FMQ
* 2) Execute a model with the given information
* 3) Send the result to the created FMQ
*
* @param callback Callback used to retrieve memories corresponding to
* unrecognized slots.
* @param requestChannel Input FMQ channel through which the client passes the
* request to the service.
* @param resultChannel Output FMQ channel from which the client can retrieve
* the result of the execution.
* @param executorWithCache Object which maintains a local cache of the
* memory pools and executes using the cached memory pools.
* @result IBurstContext Handle to the burst context.
*/
static sp<ExecutionBurstServer> create(
const sp<IBurstCallback>& callback, const FmqRequestDescriptor& requestChannel,
const FmqResultDescriptor& resultChannel,
std::shared_ptr<IBurstExecutorWithCache> executorWithCache);
/**
* Create automated context to manage FMQ-based executions.
*
* This function is intended to be used by a service to automatically:
* 1) Receive data from a provided FMQ
* 2) Execute a model with the given information
* 3) Send the result to the created FMQ
*
* @param callback Callback used to retrieve memories corresponding to
* unrecognized slots.
* @param requestChannel Input FMQ channel through which the client passes the
* request to the service.
* @param resultChannel Output FMQ channel from which the client can retrieve
* the result of the execution.
* @param preparedModel PreparedModel that the burst object was created from.
* IPreparedModel::executeSynchronously will be used to perform the
* execution.
* @result IBurstContext Handle to the burst context.
*/
static sp<ExecutionBurstServer> create(const sp<IBurstCallback>& callback,
const FmqRequestDescriptor& requestChannel,
const FmqResultDescriptor& resultChannel,
IPreparedModel* preparedModel);
في ما يلي تنفيذ مرجعي لواجهة المعالجة المكثّفة للبيانات في ملف رمز المصدر المخصص لبرنامج التشغيل
نموذج الشبكات العصبية على الرابط
frameworks/ml/nn/driver/sample/SampleDriver.cpp
.
Return<void> SamplePreparedModel::configureExecutionBurst(
const sp<V1_2::IBurstCallback>& callback,
const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
configureExecutionBurst_cb cb) {
NNTRACE_FULL(NNTRACE_LAYER_DRIVER, NNTRACE_PHASE_EXECUTION,
"SampleDriver::configureExecutionBurst");
// Alternatively, the burst could be configured via:
// const sp<V1_2::IBurstContext> burst =
// ExecutionBurstServer::create(callback, requestChannel,
// resultChannel, this);
//
// However, this alternative representation does not include a memory map
// caching optimization, and adds overhead.
const std::shared_ptr<BurstExecutorWithCache> executorWithCache =
std::make_shared<BurstExecutorWithCache>(mModel, mDriver, mPoolInfos);
const sp<V1_2::IBurstContext> burst = ExecutionBurstServer::create(
callback, requestChannel, resultChannel, executorWithCache);
if (burst == nullptr) {
cb(ErrorStatus::GENERAL_FAILURE, {});
} else {
cb(ErrorStatus::NONE, burst);
}
return Void();
}