HAL Jaringan Neural 1.2 memperkenalkan konsep eksekusi burst. Eksekusi burst adalah urutan eksekusi dari model yang sama yang telah disiapkan dan terjadi secara berurutan dengan cepat, seperti yang berjalan pada frame pengambilan gambar kamera atau sampel audio berturut-turut. Objek burst digunakan untuk mengontrol serangkaian eksekusi burst, dan untuk mempertahankan resource antar-eksekusi, sehingga eksekusi memiliki overhead yang lebih rendah. Objek burst memungkinkan tiga pengoptimalan:
- Objek burst dibuat sebelum urutan eksekusi, dan dibebaskan saat urutan telah berakhir. Oleh karena itu, masa aktif objek burst memberi petunjuk kepada driver tentang berapa lama objek tersebut harus tetap dalam status performa tinggi.
- Objek burst dapat mempertahankan resource di antara eksekusi. Misalnya, driver dapat memetakan objek memori pada eksekusi pertama dan menyimpan pemetaan dalam objek burst untuk digunakan kembali dalam eksekusi berikutnya. Setiap resource yang di-cache dapat dilepaskan saat objek burst dihancurkan atau saat runtime NNAPI memberi tahu objek burst bahwa resource tidak lagi diperlukan.
- Objek burst menggunakan antrean pesan cepat (FMQ) untuk berkomunikasi antara proses aplikasi dan driver. Hal ini dapat mengurangi latensi karena FMQ melewati HIDL dan meneruskan data langsung ke proses lain melalui FIFO melingkar atomik dalam memori bersama. Proses konsumen tahu cara mengeluarkan item dari antrean dan memulai pemrosesan dengan meminta jumlah elemen dalam FIFO atau dengan menunggu tanda peristiwa FMQ, yang ditandai oleh produsen. Flag peristiwa ini adalah mutex ruang pengguna (futex) yang cepat.
FMQ adalah struktur data tingkat rendah yang tidak menawarkan jaminan masa aktif di seluruh proses dan tidak memiliki mekanisme bawaan untuk menentukan apakah proses di ujung FMQ lainnya berjalan seperti yang diharapkan. Akibatnya, jika produser untuk FMQ berhenti berfungsi, konsumen mungkin akan menunggu data yang tidak pernah tiba. Salah satu solusi untuk masalah ini adalah agar driver mengaitkan FMQ dengan objek burst tingkat yang lebih tinggi untuk mendeteksi kapan eksekusi burst telah berakhir.
Karena eksekusi burst beroperasi pada argumen yang sama dan menampilkan hasil yang sama dengan jalur eksekusi lainnya, FMQ yang mendasarinya harus meneruskan data yang sama ke dan dari driver layanan NNAPI. Namun, FMQ hanya dapat mentransfer jenis data lama biasa. Transfer data yang kompleks dilakukan dengan membuat serialisasi
dan mendeserialisasi buffer bertingkat (jenis vektor) langsung di FMQ, dan menggunakan
objek callback HIDL untuk mentransfer handle kumpulan memori sesuai permintaan. Sisi produsen
FMQ harus mengirim pesan permintaan atau hasil ke konsumen
secara atomik menggunakan MessageQueue::writeBlocking
jika antrean memblokir, atau
menggunakan MessageQueue::write
jika antrean tidak memblokir.
Antarmuka burst
Antarmuka burst untuk HAL Jaringan Neural dapat ditemukan di
hardware/interfaces/neuralnetworks/1.2/
dan dijelaskan di bawah. Untuk mengetahui informasi selengkapnya tentang antarmuka burst di lapisan NDK, lihat frameworks/ml/nn/runtime/include/NeuralNetworks.h
.
types.hal
types.hal
menentukan jenis data yang dikirim melalui FMQ.
FmqRequestDatum
: Satu elemen representasi serial dari objekRequest
eksekusi dan nilaiMeasureTiming
, yang dikirim melalui antrean pesan cepat.FmqResultDatum
: Satu elemen representasi berseri dari nilai yang ditampilkan dari eksekusi (ErrorStatus
,OutputShapes
, danTiming
), yang ditampilkan melalui antrean pesan cepat.
IBurstContext.hal
IBurstContext.hal
menentukan objek antarmuka HIDL yang ada di layanan Neural Networks.
IBurstContext
: Objek konteks untuk mengelola resource burst.
IBurstCallback.hal
IBurstCallback.hal
mendefinisikan objek antarmuka HIDL untuk callback yang dibuat oleh runtime Neural Networks
dan digunakan oleh layanan Neural Networks untuk mengambil objek hidl_memory
yang sesuai dengan ID slot.
- IBurstCallback: Objek callback yang digunakan oleh layanan untuk mengambil objek memori.
IPreparedModel.hal
IPreparedModel.hal
diperluas di HAL 1.2 dengan metode untuk membuat objek IBurstContext
dari model yang disiapkan.
configureExecutionBurst
: Mengonfigurasi objek burst yang digunakan untuk menjalankan beberapa inferensi pada model yang disiapkan secara berurutan dengan cepat.
Mendukung eksekusi burst di driver
Cara paling sederhana untuk mendukung objek burst dalam layanan NNAPI HIDL adalah dengan menggunakan
fungsi utilitas burst ::android::nn::ExecutionBurstServer::create
, yang
ditemukan di
ExecutionBurstServer.h
dan dikemas dalam library statis libneuralnetworks_common
dan libneuralnetworks_util
. Fungsi factory ini memiliki dua kelebihan:
- Satu overload menerima pointer ke objek
IPreparedModel
. Fungsi utilitas ini menggunakan metodeexecuteSynchronously
dalam objekIPreparedModel
untuk mengeksekusi model. - Satu muatan berlebih menerima objek
IBurstExecutorWithCache
yang dapat disesuaikan, yang dapat digunakan untuk menyimpan cache resource (seperti pemetaanhidl_memory
) yang tetap ada di beberapa eksekusi.
Setiap kelebihan beban menampilkan objek IBurstContext
(yang merepresentasikan objek
burst) yang berisi dan mengelola thread pendengarnya sendiri yang khusus. Thread ini menerima permintaan dari FMQ requestChannel
, melakukan inferensi, lalu menampilkan hasilnya melalui FMQ resultChannel
. Thread ini dan semua resource lain yang ada dalam objek IBurstContext
akan otomatis dilepaskan saat klien burst kehilangan referensinya ke IBurstContext
.
Atau, Anda dapat membuat implementasi IBurstContext
sendiri yang memahami cara mengirim dan menerima pesan melalui requestChannel
dan resultChannel
FMQ yang diteruskan ke IPreparedModel::configureExecutionBurst
.
Fungsi utilitas burst dapat ditemukan di
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);
Berikut adalah implementasi referensi antarmuka burst yang ditemukan di
driver contoh Jaringan Neural di
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();
}