Neural Networks HAL 1.2 memperkenalkan konsep eksekusi burst. Beruntun eksekusi adalah urutan eksekusi model siap yang sama yang terjadi di urutan yang cepat, seperti yang beroperasi pada bingkai pengambilan gambar kamera atau audio berurutan sampel. Objek burst digunakan untuk mengontrol serangkaian eksekusi burst, dan untuk mempertahankan resource di antara eksekusi, memungkinkan eksekusi memiliki overhead. Objek burst memungkinkan tiga pengoptimalan:
- Objek burst dibuat sebelum urutan eksekusi, dan dibebaskan ketika urutan telah berakhir. Karena itu, masa pakai burst petunjuk objek kepada driver berapa lama harus tetap dalam performa tinggi status.
- Objek burst dapat mempertahankan resource di antara eksekusi. Sebagai contoh, {i>driver<i} dapat memetakan objek memori pada eksekusi pertama dan meng-cache pemetaan dalam objek burst untuk digunakan kembali dalam eksekusi berikutnya. Semua resource yang di-cache dapat dirilis saat objek burst dihancurkan atau ketika NNAPI runtime memberi tahu objek burst bahwa resource tidak lagi diperlukan.
- Sebuah 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 secara langsung ke proses lain melalui FIFO sirkular atom dalam memori bersama. Tujuan proses konsumen mengetahui untuk menarik barang ke dalam antrean dan mulai memprosesnya melakukan polling jumlah elemen di FIFO atau dengan menunggu peristiwa FMQ yang ditandai oleh produsen. Penanda peristiwa ini adalah userspace mutex (futex).
FMQ adalah struktur data tingkat rendah yang tidak menawarkan jaminan sepanjang waktu proses dan tidak memiliki mekanisme bawaan untuk menentukan apakah proses di atas ujung lain FMQ berjalan seperti yang diharapkan. Sehingga, jika produser untuk FMQ mati, konsumen mungkin terjebak menunggu data yang tidak pernah tiba. paket Premium AI Solusi untuk masalah ini adalah pengemudi menghubungkan FMQ dengan dengan level yang lebih tinggi untuk mendeteksi saat eksekusi burst berakhir.
Karena eksekusi burst beroperasi pada argumen yang sama dan menampilkan nilai yang sama
sebagai jalur eksekusi lain, FMQ yang mendasarinya harus meneruskan data yang sama ke
dan dari driver layanan NNAPI. Namun, FMQ hanya dapat mentransfer
tipe data biasa yang lama. Mentransfer data yang kompleks
dilakukan dengan serialisasi
dan melakukan deserialisasi buffer bertingkat (jenis vektor) langsung di FMQ, dan menggunakan
Objek callback HIDL untuk mentransfer handle memori sesuai permintaan. Produser
sisi FMQ harus mengirim pesan permintaan atau hasil ke konsumen
secara atomik menggunakan MessageQueue::writeBlocking
jika antrean memblokir, atau
dengan menggunakan MessageQueue::write
jika antrean tidak memblokir.
Antarmuka burst
Antarmuka burst untuk HAL Jaringan Neural ditemukan di
hardware/interfaces/neuralnetworks/1.2/
dan dijelaskan di bawah ini. Untuk informasi selengkapnya tentang antarmuka burst di NDK
lapisan, lihat
frameworks/ml/nn/runtime/include/NeuralNetworks.h
types.hal
types.hal
menentukan jenis data yang dikirim melalui FMQ.
FmqRequestDatum
: Elemen tunggal representasi serial dariRequest
eksekusi dan nilaiMeasureTiming
, yang dikirim melalui pesan cepat antrean.FmqResultDatum
: Elemen tunggal dari representasi serial dari nilai-nilai yang dikembalikan eksekusi (ErrorStatus
,OutputShapes
, danTiming
), yang dikembalikan melalui antrean pesan cepat.
{i>IBurstContext.hal<i}
IBurstContext.hal
mendefinisikan objek antarmuka HIDL yang berada dalam layanan Jaringan Neural.
IBurstContext
: Objek konteks untuk mengelola resource burst.
IBurstCallback.hal
IBurstCallback.hal
menentukan objek antarmuka HIDL untuk callback yang dibuat oleh Jaringan Neural
runtime dan digunakan oleh layanan Jaringan Neural untuk mengambil hidl_memory
objek 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 sudah disiapkan.
configureExecutionBurst
: Mengonfigurasi objek burst yang digunakan untuk menjalankan beberapa inferensi pada model ini dengan cepat.
Mendukung eksekusi burst dalam driver
Cara paling sederhana untuk mendukung objek burst dalam layanan HIDL NNAPI adalah dengan menggunakan
fungsi utilitas burst ::android::nn::ExecutionBurstServer::create
, yaitu
ditemukan di
ExecutionBurstServer.h
serta dikemas dalam libneuralnetworks_common
dan libneuralnetworks_util
library statis. Fungsi factory ini memiliki dua overload:
- Satu overload menerima pointer ke objek
IPreparedModel
. Ini fungsi utilitas menggunakan metodeexecuteSynchronously
dalamIPreparedModel
untuk mengeksekusi model. - Satu overload menerima objek
IBurstExecutorWithCache
yang dapat disesuaikan, yang dapat digunakan untuk menyimpan resource ke cache (seperti pemetaanhidl_memory
) yang tetap ada di beberapa eksekusi.
Setiap overload menampilkan objek IBurstContext
(yang mewakili burst
) yang berisi dan mengelola thread pemroses khusus miliknya sendiri. Rangkaian pesan ini
menerima permintaan dari FMQ requestChannel
, melakukan inferensi, lalu
menampilkan hasilnya melalui resultChannel
FMQ. Rangkaian pesan ini dan semua
resource yang terdapat dalam objek IBurstContext
akan otomatis dirilis
saat klien burst kehilangan referensinya ke IBurstContext
.
Atau, Anda dapat membuat implementasi IBurstContext
Anda sendiri yang
memahami cara mengirim dan menerima pesan melalui requestChannel
dan
resultChannel
FMQ diteruskan ke IPreparedModel::configureExecutionBurst
.
Fungsi utilitas {i>burst<i} 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 ini adalah implementasi referensi antarmuka burst yang terdapat dalam
Contoh driver 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();
}