類神經網路 HAL 1.2 介紹爆發執行的概念。火花 「執行作業」是指在 像是在相機拍攝畫面中運作 連續音訊 樣本。爆發物件可用於控制一組爆發執行作業 保留執行作業之間的資源,讓執行作業能減少 同時免除不必要的負擔爆發物件支援三種最佳化功能:
- 系統會在執行一系列執行作業前建立爆發物件 序列結束時因此,連拍的生命週期 並向驅動程式提示駕駛人應能維持高效能物件的時間長度 時間。
- 爆發物件可以保留執行作業之間的資源。舉例來說 驅動程式可在首次執行時對應記憶體物件,並快取對應 放入爆發物件中,以便在後續執行作業中重複使用。任何快取的資源 等到爆發物件刪除或 NNAPI 後 執行階段會通知爆發物件,說明不再需要資源。
- 爆發物件會使用 快速訊息佇列 (FMQ) 以在應用程式和驅動程式程序之間進行通訊。這可以 降低延遲時間,因為 FMQ 會略過 HIDL,並將資料直接傳送給 透過共用記憶體中的原子環 FIFO 通過另一個程序。 消費者程序知道將項目移出佇列並由以下兩個方法開始處理: 輪詢 FIFO 或 FMQ 事件的數目 標記,並由生產者發出訊號。這個事件旗標是非常快速 使用者空間互斥鎖 (futex)。
FMQ 是一種低階資料結構,在 且沒有內建可判斷處理程序 FMQ 另一端運作正常。因此如果生產端 FMQ 公司因此難免會卡住一 此問題的解決方法,是駕駛人將 FMQ 與 來偵測爆發執行何時結束。
因為爆發執行作業會在相同的引數上運作
與其他執行路徑一樣,基礎 FMQ 必須將相同的資料傳送至
以及依據 NNAPI 服務驅動程式不過,FMQ 只能轉
純粹的資料型別將複雜資料序列化即可完成移轉
以及直接在 FMQ 中反序列化巢狀緩衝區 (向量類型),然後使用
用於轉移記憶體集區的 HIDL 回呼物件。製作人
FMQ 最終必須將要求或結果訊息傳送給用戶端
如果佇列處於封鎖狀態,則使用 MessageQueue::writeBlocking
,或者
如果佇列為非阻斷式,請使用 MessageQueue::write
。
爆發介面
類神經網路 HAL 的爆發介面位於
hardware/interfaces/neuralnetworks/1.2/
敬上
。請參閱 NDK 中爆發介面的詳細資訊
圖層,請參閱
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 介面物件
執行階段,並由類神經網路服務用來擷取 hidl_memory
對應至運算單元 ID 的物件
- 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();
}