Halaman ini menjelaskan struktur data dan metode yang digunakan untuk mengomunikasikan buffer operand secara efisien antara driver dan framework.
Pada waktu kompilasi model, kerangka kerja memberikan nilai operan konstan ke driver. Bergantung pada masa pakai operan konstan, nilainya terletak di vektor HIDL atau kumpulan memori bersama.
- Jika masa pakainya adalah
CONSTANT_COPY
, nilainya terletak di bidangoperandValues
dari struktur model. Karena nilai dalam vektor HIDL disalin selama komunikasi antarproses (IPC), ini biasanya digunakan hanya untuk menampung sejumlah kecil data seperti operan skalar (misalnya, skalar aktivasi diADD
) dan parameter tensor kecil (misalnya, bentuk tensor diRESHAPE
). - Jika masa pakainya adalah
CONSTANT_REFERENCE
, nilainya terletak di bidangpools
struktur model. Hanya pegangan dari kumpulan memori bersama yang diduplikasi selama IPC daripada menyalin nilai mentah. Oleh karena itu, lebih efisien untuk menyimpan data dalam jumlah besar (misalnya, parameter bobot dalam konvolusi) menggunakan kumpulan memori bersama daripada vektor HIDL.
Pada waktu eksekusi model, framework menyediakan buffer operand input dan output ke driver. Tidak seperti konstanta waktu kompilasi yang mungkin dikirim dalam vektor HIDL, data input dan output dari suatu eksekusi selalu dikomunikasikan melalui kumpulan kumpulan memori.
Tipe data hidl_memory
digunakan dalam kompilasi dan eksekusi untuk mewakili kumpulan memori bersama yang tidak dipetakan. Pengemudi harus memetakan memori yang sesuai untuk membuatnya dapat digunakan berdasarkan nama tipe data hidl_memory
. Nama memori yang didukung adalah:
-
ashmem
: memori bersama Android. Untuk lebih jelasnya, lihat memori . -
mmap_fd
: Memori bersama yang didukung oleh deskriptor file melaluimmap
. -
hardware_buffer_blob
: Memori bersama yang didukung oleh AHardwareBuffer dengan formatAHARDWARE_BUFFER_FORMAT_BLOB
. Tersedia dari Neural Networks (NN) HAL 1.2. Untuk detail selengkapnya, lihat AHardwareBuffer . -
hardware_buffer
: Memori bersama yang didukung oleh AHardwareBuffer umum yang tidak menggunakan formatAHARDWARE_BUFFER_FORMAT_BLOB
. Buffer perangkat keras mode non-BLOB hanya didukung dalam eksekusi model. Tersedia dari NN HAL 1.2. Untuk detail selengkapnya, lihat AHardwareBuffer .
Dari NN HAL 1.3, NNAPI mendukung domain memori yang menyediakan antarmuka pengalokasi untuk buffer yang dikelola driver. Buffer yang dikelola driver juga dapat digunakan sebagai input atau output eksekusi. Untuk detail selengkapnya, lihat Domain memori .
Driver NNAPI harus mendukung pemetaan nama memori ashmem
dan mmap_fd
. Dari NN HAL 1.3, driver juga harus mendukung pemetaan hardware_buffer_blob
. Dukungan untuk hardware_buffer
mode non-BLOB umum dan domain memori adalah opsional.
AHardwareBuffer
AHardwareBuffer adalah jenis memori bersama yang membungkus buffer Gralloc . Di Android 10, Neural Networks API (NNAPI) mendukung penggunaan AHardwareBuffer , yang memungkinkan pengemudi melakukan eksekusi tanpa menyalin data, yang meningkatkan kinerja dan konsumsi daya untuk aplikasi. Misalnya, tumpukan HAL kamera dapat meneruskan objek AHardwareBuffer ke NNAPI untuk beban kerja pembelajaran mesin menggunakan pegangan AHardwareBuffer yang dihasilkan oleh NDK kamera dan API NDK media. Untuk informasi selengkapnya, lihat ANeuralNetworksMemory_createFromAHardwareBuffer
.
Objek AHardwareBuffer yang digunakan dalam NNAPI diteruskan ke driver melalui struct hidl_memory
bernama hardware_buffer
atau hardware_buffer_blob
. hidl_memory
struct hardware_buffer_blob
hanya mewakili objek AHardwareBuffer dengan format AHARDWAREBUFFER_FORMAT_BLOB
.
Informasi yang diperlukan oleh kerangka kerja dikodekan dalam bidang hidl_handle
dari struct hidl_memory
. Bidang hidl_handle
membungkus native_handle
, yang mengkodekan semua metadata yang diperlukan tentang buffer AHardwareBuffer atau Gralloc.
Pengemudi harus benar memecahkan kode bidang hidl_handle
yang disediakan dan mengakses memori yang dijelaskan oleh hidl_handle
. Ketika metode getSupportedOperations_1_2
, getSupportedOperations_1_1
, atau getSupportedOperations
dipanggil, pengemudi harus mendeteksi apakah ia dapat memecahkan kode hidl_handle
yang disediakan dan mengakses memori yang dijelaskan oleh hidl_handle
. Persiapan model harus gagal jika bidang hidl_handle
yang digunakan untuk operan konstan tidak didukung. Eksekusi harus gagal jika bidang hidl_handle
yang digunakan untuk operan input atau output eksekusi tidak didukung. Direkomendasikan bagi driver untuk mengembalikan kode kesalahan GENERAL_FAILURE
jika persiapan model atau eksekusi gagal.
Domain memori
Untuk perangkat yang menjalankan Android 11 atau lebih tinggi, NNAPI mendukung domain memori yang menyediakan antarmuka pengalokasi untuk buffer yang dikelola driver. Hal ini memungkinkan untuk melewatkan memori asli perangkat di seluruh eksekusi, menekan penyalinan data yang tidak perlu dan transformasi antara eksekusi berurutan pada driver yang sama. Aliran ini diilustrasikan pada Gambar 1.
Gambar 1. Aliran data buffer menggunakan domain memori
Fitur domain memori ditujukan untuk tensor yang sebagian besar bersifat internal pada driver dan tidak memerlukan akses yang sering di sisi klien. Contoh tensor tersebut termasuk tensor keadaan dalam model urutan. Untuk tensor yang sering membutuhkan akses CPU di sisi klien, lebih baik menggunakan kumpulan memori bersama.
Untuk mendukung fitur domain memori, terapkan IDevice::allocate
untuk mengizinkan framework meminta alokasi buffer yang dikelola driver. Selama alokasi, framework menyediakan properti dan pola penggunaan berikut untuk buffer:
-
BufferDesc
menjelaskan properti yang diperlukan dari buffer. -
BufferRole
menggambarkan potensi pola penggunaan buffer sebagai input atau output dari model yang disiapkan. Beberapa peran dapat ditentukan selama alokasi buffer, dan buffer yang dialokasikan hanya dapat digunakan sebagai peran yang ditentukan.
Buffer yang dialokasikan bersifat internal untuk driver. Pengemudi dapat memilih lokasi buffer atau tata letak data apa pun. Ketika buffer berhasil dialokasikan, klien driver dapat mereferensikan atau berinteraksi dengan buffer menggunakan token yang dikembalikan atau objek IBuffer
.
Token dari IDevice::allocate
disediakan saat mereferensikan buffer sebagai salah satu objek MemoryPool
dalam struktur Request
dari suatu eksekusi. Untuk mencegah proses mencoba mengakses buffer yang dialokasikan dalam proses lain, driver harus menerapkan validasi yang tepat pada setiap penggunaan buffer. Pengemudi harus memvalidasi bahwa penggunaan buffer adalah salah satu peran BufferRole
yang disediakan selama alokasi dan harus segera gagal dalam eksekusi jika penggunaannya ilegal.
Objek IBuffer
digunakan untuk menyalin memori eksplisit. Dalam situasi tertentu, klien pengandar harus menginisialisasi buffer yang dikelola driver dari kumpulan memori bersama atau menyalin buffer ke kumpulan memori bersama. Contoh kasus penggunaan meliputi:
- Inisialisasi tensor keadaan
- Caching hasil antara
- Eksekusi mundur pada CPU
Untuk mendukung kasus penggunaan ini, driver harus mengimplementasikan IBuffer::copyTo
dan IBuffer::copyFrom
dengan ashmem
, mmap_fd
, dan hardware_buffer_blob
jika mendukung alokasi domain memori. Ini opsional bagi driver untuk mendukung mode non-BLOB hardware_buffer
.
Selama alokasi buffer, dimensi buffer dapat disimpulkan dari operan model yang sesuai dari semua peran yang ditentukan oleh BufferRole
, dan dimensi yang disediakan di BufferDesc
. Dengan semua informasi dimensi digabungkan, buffer mungkin memiliki dimensi atau peringkat yang tidak diketahui. Dalam kasus seperti itu, buffer berada dalam keadaan fleksibel di mana dimensinya tetap ketika digunakan sebagai input model dan dalam keadaan dinamis ketika digunakan sebagai output model. Buffer yang sama dapat digunakan dengan bentuk keluaran yang berbeda dalam eksekusi yang berbeda dan driver harus menangani pengubahan ukuran buffer dengan benar.
Domain memori adalah fitur opsional. Pengemudi dapat menentukan bahwa itu tidak dapat mendukung permintaan alokasi yang diberikan karena sejumlah alasan. Sebagai contoh:
- Buffer yang diminta memiliki ukuran dinamis.
- Pengemudi memiliki batasan memori yang mencegahnya menangani buffer besar.
Beberapa utas berbeda dapat dibaca dari buffer yang dikelola driver secara bersamaan. Mengakses buffer secara bersamaan untuk menulis atau membaca/menulis tidak ditentukan, tetapi tidak boleh membuat crash layanan driver atau memblokir pemanggil tanpa batas. Pengemudi dapat mengembalikan kesalahan atau membiarkan konten buffer dalam keadaan tak tentu.