Neural Networks HAL 1.2 เปิดตัวแนวคิดการดำเนินการแบบระเบิด การดำเนินการแบบต่อเนื่องคือลําดับการดำเนินการของโมเดลที่เตรียมไว้แบบเดียวกันซึ่งเกิดขึ้นอย่างต่อเนื่อง เช่น การดำเนินการกับเฟรมของภาพจากกล้องหรือตัวอย่างเสียงที่ต่อเนื่องกัน วัตถุระเบิดใช้เพื่อควบคุมชุดของการถ่ายภาพอัจฉริยะ และเพื่อ รักษาทรัพยากรระหว่างการดำเนินการต่างๆ ไว้ ทำให้การดำเนินการมี โอเวอร์เฮด วัตถุที่ถ่ายต่อเนื่องกันทำให้สามารถเพิ่มประสิทธิภาพได้ 3 แบบ ดังนี้
- ออบเจ็กต์ภาพถ่ายอัจฉริยะจะสร้างขึ้นก่อนการดำเนินการตามลำดับ และได้รับการปล่อยให้เป็นอิสระ เมื่อลำดับสิ้นสุดลง ด้วยเหตุนี้ อายุการใช้งานของการถ่ายภาพอัจฉริยะ การแนะนำวัตถุให้ผู้ขับขี่ทราบว่ารถควรอยู่ในสมรรถนะดีนานเท่าใด
- ออบเจ็กต์ต่อเนื่องสามารถเก็บรักษาทรัพยากรระหว่างการดำเนินการได้ ตัวอย่างเช่น ไดรเวอร์สามารถจับคู่ออบเจ็กต์หน่วยความจำในการดำเนินการครั้งแรกและแคชการแมป ในออบเจ็กต์ภาพถ่ายอัจฉริยะเพื่อใช้ซ้ำในการดำเนินการครั้งต่อๆ ไป ทรัพยากรที่แคชไว้ สามารถปล่อยตัวได้เมื่อวัตถุระเบิดถูกทำลายหรือเมื่อ NNAPI รันไทม์จะแจ้งเตือนออบเจ็กต์อัจฉริยะว่าไม่จำเป็นต้องใช้ทรัพยากรอีกต่อไป
- ออบเจ็กต์การระเบิดใช้คิวข้อความที่รวดเร็ว (FMQ) เพื่อสื่อสารระหว่างแอปกับกระบวนการของไดรเวอร์ ซึ่งช่วยลดเวลาในการตอบสนองได้ เนื่องจาก FMQ จะข้าม HIDL และส่งข้อมูลไปยังกระบวนการอื่นโดยตรงผ่าน FIFO แบบวนซ้ำแบบอะตอมในหน่วยความจำที่ใช้ร่วมกัน กระบวนการของผู้บริโภคจะรู้ว่าต้องนำรายการออกจากคิวและเริ่มประมวลผลโดยตรวจสอบจำนวนองค์ประกอบใน FIFO หรือรอสัญญาณ Flag เหตุการณ์ของ FMQ ซึ่งผู้ผลิตส่งสัญญาณ Flag เหตุการณ์นี้เป็นมิวเทคส์ (futex) เฉพาะพื้นที่ผู้ใช้ที่ทำงานอย่างรวดเร็ว
FMQ คือโครงสร้างข้อมูลที่ระดับล่างซึ่งไม่มีการรับประกันตลอดอายุการใช้งานสำหรับกระบวนการต่างๆ และไม่มีกลไกในตัวสำหรับพิจารณาว่ากระบวนการที่อีกฝั่งหนึ่งของ FMQ ทำงานตามที่คาดไว้หรือไม่ ดังนั้น หากผู้สร้าง FMQ ลดลง ผู้บริโภคอาจต้องนั่งรอข้อมูลที่ไม่เคยมาถึง วิธีแก้ปัญหาอย่างหนึ่งคือให้ไดรเวอร์เชื่อมโยง FMQ กับออบเจ็กต์การระเบิดระดับที่สูงขึ้นเพื่อตรวจหาเมื่อการเรียกใช้การระเบิดสิ้นสุดลง
เนื่องจากการดำเนินการแบบระเบิดจะทำงานกับอาร์กิวเมนต์เดียวกันและแสดงผลลัพธ์เดียวกันกับเส้นทางการดําเนินการอื่นๆ FMQ พื้นฐานจึงต้องส่งข้อมูลเดียวกันไปยังและจากไดรเวอร์บริการ NNAPI อย่างไรก็ตาม FMQ จะโอนได้เท่านั้น
ประเภทข้อมูลเก่า การถ่ายโอนข้อมูลที่ซับซ้อนสามารถทำได้ด้วยการเรียงลำดับ
และดีซีเรียลไลซ์บัฟเฟอร์ที่ซ้อนกัน (ประเภทเวกเตอร์) โดยตรงใน FMQ และใช้
ออบเจ็กต์ Callback HIDL เพื่อโอนแฮนเดิลพูลหน่วยความจำตามคำขอ ฝั่งผู้ผลิตของ FMQ ต้องส่งข้อความคำขอหรือผลลัพธ์ไปยังฝั่งผู้บริโภคแบบเป็นกลุ่มโดยใช้ MessageQueue::writeBlocking
หากคิวเป็นแบบบล็อก หรือใช้ MessageQueue::write
หากคิวเป็นแบบไม่บล็อก
อินเทอร์เฟซของภาพถ่ายแบบ Burst
พบอินเทอร์เฟซแบบต่อเนื่องสำหรับ HAL โครงข่ายระบบประสาทเทียมใน
hardware/interfaces/neuralnetworks/1.2/
และอธิบายไว้ด้านล่าง ดูข้อมูลเพิ่มเติมเกี่ยวกับอินเทอร์เฟซการถ่ายภาพหลายช็อตในเลเยอร์ NDK ได้ที่ frameworks/ml/nn/runtime/include/NeuralNetworks.h
Type.hal
types.hal
กำหนดประเภทข้อมูลที่ส่งผ่าน FMQ
FmqRequestDatum
องค์ประกอบเดี่ยวของการแสดงการดำเนินการRequest
แบบต่อเนื่อง และค่าMeasureTiming
ซึ่งจะส่งผ่านข้อความแบบเร็ว คิวFmqResultDatum
องค์ประกอบเดียวของการแสดงค่าที่ส่งคืนจากแบบอนุกรม การดำเนินการ (ErrorStatus
,OutputShapes
และTiming
) แสดงผลผ่านคิวข้อความที่รวดเร็ว
IBurstContext.hal
IBurstContext.hal
กำหนดออบเจ็กต์อินเทอร์เฟซ HIDL ที่อยู่ในบริการเครือข่ายประสาทเทียม
IBurstContext
ออบเจ็กต์บริบทสำหรับจัดการทรัพยากรของภาพถ่ายอัจฉริยะ
IBurstCallback.hal
IBurstCallback.hal
กำหนดออบเจ็กต์อินเทอร์เฟซ HIDL สำหรับ Callback ที่สร้างโดยโครงข่ายระบบประสาทเทียม
รันไทม์และใช้โดยบริการเครือข่ายระบบประสาทเพื่อเรียกข้อมูล hidl_memory
ที่สอดคล้องกับตัวระบุช่อง
- IBurstCallback: ออบเจ็กต์ Callback ที่บริการใช้ในการเรียกออบเจ็กต์หน่วยความจำ
IPreparedModel.hal
IPreparedModel.hal
ได้รับการขยายใน HAL 1.2 ด้วยเมธอดในการสร้างออบเจ็กต์ IBurstContext
จากโมเดลที่เตรียมไว้
configureExecutionBurst
กำหนดค่าออบเจ็กต์ภาพถ่ายอัจฉริยะซึ่งใช้เพื่อดำเนินการอนุมานหลายรายการในชุดข้อมูลที่เตรียมไว้ แบบต่อเนื่องอย่างรวดเร็ว
รองรับการดำเนินการแบบต่อเนื่องในไดรเวอร์
วิธีที่ง่ายที่สุดในการรองรับวัตถุระเบิดในบริการ HIDL NNAPI คือการใช้
ฟังก์ชันถ่ายภาพอัจฉริยะ ::android::nn::ExecutionBurstServer::create
ซึ่ง
พบใน
ExecutionBurstServer.h
และบรรจุหีบห่อในlibneuralnetworks_common
และlibneuralnetworks_util
และไลบรารีแบบคงที่ ฟังก์ชันโรงงานนี้มีโอเวอร์โหลด 2 แบบ:
- โอเวอร์โหลด 1 รายการยอมรับตัวชี้ไปยังออบเจ็กต์
IPreparedModel
ช่วงเวลานี้ ฟังก์ชันยูทิลิตีใช้เมธอดexecuteSynchronously
ในIPreparedModel
เพื่อเรียกใช้โมเดล - โอเวอร์โหลด 1 รายการยอมรับออบเจ็กต์
IBurstExecutorWithCache
ที่ปรับแต่งได้ ซึ่งใช้เพื่อแคชทรัพยากร (เช่น การแมปhidl_memory
) ที่ คงอยู่ในการดําเนินการหลายอย่าง
การโอเวอร์โหลดแต่ละรายการจะแสดงผลออบเจ็กต์ IBurstContext
(ซึ่งแสดงออบเจ็กต์ Burst) ที่มีและจัดการเธรดผู้ฟังเฉพาะของตนเอง เทรดนี้รับคําขอจาก FMQ requestChannel
ดําเนินการอนุมาน แล้วแสดงผลลัพธ์ผ่าน FMQ resultChannel
ระบบจะปล่อยชุดข้อความนี้และทรัพยากรอื่นๆ ทั้งหมดที่อยู่ในออบเจ็กต์ IBurstContext
โดยอัตโนมัติเมื่อไคลเอ็นต์ของพุลส์สูญเสียการอ้างอิงถึง IBurstContext
หรือจะสร้างการใช้งาน IBurstContext
ของคุณเองก็ได้ ซึ่งจะเข้าใจวิธีส่งและรับข้อความผ่าน FMQ ของ requestChannel
และ resultChannel
ที่ส่งไปยัง 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);
ต่อไปนี้เป็นการใช้งานอ้างอิงสำหรับอินเทอร์เฟซ Burst ที่พบในไดรเวอร์ตัวอย่างของ Neural Networks ที่ 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();
}