يقدم HAL 1.2 للشبكات العصبية مفهوم عمليات الإعدام المتقطعة. عمليات تنفيذ الاندفاع هي سلسلة من عمليات التنفيذ لنفس النموذج المُعد والتي تحدث في تتابع سريع ، مثل تلك التي تعمل على إطارات التقاط الكاميرا أو عينات الصوت المتتالية. يتم استخدام كائن الاندفاع للتحكم في مجموعة من عمليات تنفيذ الاندفاع ، وللحفاظ على الموارد بين عمليات التنفيذ ، مما يتيح لعمليات التنفيذ أن يكون لها مقدار حمل أقل. تمكّن كائنات الاندفاع ثلاثة تحسينات:
- يتم إنشاء كائن الاندفاع قبل سلسلة من عمليات التنفيذ ، ويتم تحريره عند انتهاء التسلسل. لهذا السبب ، فإن عمر كائن الاندفاع يلمح للسائق إلى متى يجب أن يظل في حالة أداء عالٍ.
- يمكن أن يحافظ كائن الاندفاع على الموارد بين عمليات التنفيذ. على سبيل المثال ، يمكن للسائق تعيين كائن ذاكرة عند التنفيذ الأول والتخزين المؤقت للتعيين في كائن الاندفاع لإعادة استخدامه في عمليات التنفيذ اللاحقة. يمكن تحرير أي مورد تم تخزينه مؤقتًا عند إتلاف كائن الاندفاع أو عندما يقوم وقت تشغيل NNAPI بإعلام كائن الاندفاع بأن المورد لم يعد مطلوبًا.
- يستخدم كائن الاندفاع قوائم انتظار الرسائل السريعة (FMQs) للتواصل بين عمليات التطبيق والسائق. يمكن أن يقلل هذا من زمن الوصول لأن FMQ يتجاوز HIDL ويمرر البيانات مباشرة إلى عملية أخرى من خلال FIFO دائري ذري في الذاكرة المشتركة. تعرف عملية المستهلك إلغاء ترتيب عنصر ما والبدء في المعالجة إما عن طريق استقصاء عدد العناصر في الوارد أولاً يصرف أولاً أو عن طريق الانتظار على علامة حدث FMQ ، والتي يشير إليها المنتج. علامة الحدث هذه عبارة عن كائن مزامنة سريع لمساحة المستخدمين (Futex).
FMQ هي بنية بيانات منخفضة المستوى لا تقدم أي ضمانات مدى الحياة عبر العمليات ولا تحتوي على آلية مضمنة لتحديد ما إذا كانت العملية على الطرف الآخر من FMQ تعمل كما هو متوقع. وبالتالي ، إذا مات منتج FMQ ، فقد يكون المستهلك عالقًا في انتظار البيانات التي لا تصل أبدًا. يتمثل أحد الحلول لهذه المشكلة في أن يقوم السائق بربط FMQs بجسم الاندفاع ذي المستوى الأعلى لاكتشاف وقت انتهاء تنفيذ الاندفاع.
نظرًا لأن عمليات تنفيذ الاندفاع تعمل على نفس الوسيطات وإرجاع نفس النتائج مثل مسارات التنفيذ الأخرى ، يجب أن تمرر FMQs الأساسية البيانات نفسها من برامج تشغيل خدمة NNAPI وإليها. ومع ذلك ، يمكن لـ FMQs نقل أنواع البيانات القديمة فقط. يتم نقل البيانات المعقدة عن طريق إجراء تسلسل وإلغاء تسلسل المخازن المؤقتة المتداخلة (أنواع المتجهات) مباشرة في FMQs ، واستخدام كائنات رد اتصال HIDL لنقل مقابض تجمع الذاكرة عند الطلب. يجب أن يرسل جانب المنتج في FMQ الطلب أو رسائل النتائج إلى المستهلك تلقائيًا باستخدام MessageQueue::writeBlocking
إذا كانت قائمة الانتظار محظورة ، أو باستخدام MessageQueue::write
إذا كانت قائمة الانتظار غير محظورة.
واجهات انفجر
تم العثور على واجهات الاندفاع للشبكات العصبية HAL في hardware/interfaces/neuralnetworks/1.2/
وهي موصوفة أدناه. لمزيد من المعلومات حول واجهات الاندفاع في طبقة NDK ، راجع frameworks/ml/nn/runtime/include/NeuralNetworks.h
.
أنواع
تحدد types.hal
نوع البيانات التي يتم إرسالها عبر FMQ.
-
FmqRequestDatum
: عنصر واحد لتمثيل متسلسل لكائنRequest
تنفيذ وقيمةMeasureTiming
، والتي يتم إرسالها عبر قائمة انتظار الرسائل السريعة. -
FmqResultDatum
: عنصر واحد لتمثيل متسلسل للقيم التي يتم إرجاعها من تنفيذ (ErrorStatus
وOutputShapes
وTiming
) ، والتي يتم إرجاعها من خلال قائمة انتظار الرسائل السريعة.
IBurstContext.hal
يعرّف IBurstContext.hal
كائن واجهة HIDL الذي يعيش في خدمة الشبكات العصبية.
-
IBurstContext
: كائن سياق لإدارة موارد الرشقة.
IBurstCallback.hal
يعرّف IBurstCallback.hal
كائن واجهة HIDL لرد الاتصال الذي تم إنشاؤه بواسطة وقت تشغيل الشبكات العصبية ويتم استخدامه بواسطة خدمة الشبكات العصبية لاسترداد كائنات 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
. يتم تحرير هذا الخيط وجميع الموارد الأخرى الموجودة في كائن IBurstContext
تلقائيًا عندما يفقد عميل الدفعة مرجعها إلى IBurstContext
.
بدلاً من ذلك ، يمكنك إنشاء التطبيق الخاص بك لـ IBurstContext
الذي يفهم كيفية إرسال واستقبال الرسائل عبر requestChannel
و resultChannel
FMQs التي تم تمريرها إلى 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();
}