Halaman ini menjelaskan struktur dan metode data yang digunakan untuk mengomunikasikan buffer operand antara driver dan framework secara efisien.
Pada waktu kompilasi model, framework akan memberikan nilai operand konstan ke driver. Bergantung pada masa aktif operand konstanta, nilainya berada dalam vektor HIDL atau gabungan memori bersama.
- Jika masa aktifnya adalah
CONSTANT_COPY
, nilai tersebut berada di kolomoperandValues
dalam struktur model. Karena nilai dalam vektor HIDL disalin selama komunikasi antarproses (IPC), nilai ini biasanya hanya digunakan untuk menampung data dalam jumlah kecil seperti operand skalar (misalnya, skalar aktivasi dalamADD
) dan parameter tensor kecil (misalnya, tensor bentuk diRESHAPE
). - Jika masa aktifnya adalah
CONSTANT_REFERENCE
, nilai tersebut berada di kolompools
dalam struktur model. Hanya tuas kumpulan memori bersama yang diduplikasi selama IPC, bukan menyalin nilai mentah. Oleh karena itu, akan 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 eksekusi selalu dikomunikasikan melalui kumpulan kumpulan memori.
Jenis data HIDL hidl_memory
digunakan dalam kompilasi dan eksekusi untuk
menampilkan kumpulan memori bersama yang tidak dipetakan. Driver harus memetakan memori
sesuai agar dapat digunakan berdasarkan nama jenis data hidl_memory
.
Nama memori yang didukung adalah:
ashmem
: Kenangan bersama Android. Untuk mengetahui detail selengkapnya, 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 hardware 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 alokator untuk buffer yang dikelola driver. Buffer yang dikelola driver juga dapat digunakan sebagai input atau output eksekusi. Untuk mengetahui 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 mode non-BLOB umum hardware_buffer
dan domain memori bersifat opsional.
{i>AHardwareBuffer<i}
AHardwareBuffer adalah jenis memori bersama yang menggabungkan
buffer GTFS. Di Android
10, Neural Networks API (NNAPI) mendukung penggunaan
AHardwareBuffer
sehingga driver dapat menjalankan eksekusi tanpa menyalin data, sehingga meningkatkan
performa dan konsumsi daya untuk aplikasi. Misalnya, stack HAL kamera
dapat meneruskan objek AHardwareBuffer ke NNAPI untuk beban kerja
machine learning menggunakan tuas AHardwareBuffer yang dihasilkan oleh NDK kamera dan API
NDK media. Untuk mengetahui informasi selengkapnya, lihat
ANeuralNetworksMemory_createFromAHardwareBuffer
.
Objek AHardwareBuffer yang digunakan dalam NNAPI diteruskan ke driver melalui
struct hidl_memory
yang 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 framework dienkode dalam kolom hidl_handle
dari struct hidl_memory
. Kolom hidl_handle
menggabungkan native_handle
,
yang mengenkode semua metadata yang diperlukan tentang AHardwareBuffer atau buffer
Gralloc.
Driver harus mendekode kolom hidl_handle
yang disediakan dengan benar dan mengakses memori yang dijelaskan oleh hidl_handle
. Saat metode getSupportedOperations_1_2
,
getSupportedOperations_1_1
, atau getSupportedOperations
dipanggil, driver harus mendeteksi apakah dapat mendekode hidl_handle
yang disediakan
dan mengakses memori yang dijelaskan oleh hidl_handle
. Persiapan
model harus gagal jika kolom hidl_handle
yang digunakan untuk operand konstanta
tidak didukung. Eksekusi harus gagal jika kolom hidl_handle
yang digunakan untuk
Operand input atau output eksekusi tidak didukung. Sebaiknya
driver menampilkan kode error GENERAL_FAILURE
jika persiapan
atau eksekusi model gagal.
Domain memori
Untuk perangkat yang menjalankan Android 11 atau yang lebih tinggi, NNAPI mendukung domain memori yang menyediakan antarmuka alokator untuk buffer yang dikelola driver. Hal ini memungkinkan penerusan memori native perangkat di seluruh eksekusi, sehingga menyembunyikan dan mengubah penyalinan data yang tidak perlu antara eksekusi berurutan pada driver yang sama. Alur ini diilustrasikan pada Gambar 1.
Gambar 1. Buffering aliran data menggunakan domain memori
Fitur domain memori ditujukan untuk tensor yang sebagian besar bersifat internal bagi driver dan tidak memerlukan akses sering pada sisi klien. Contoh tensor tersebut mencakup tensor status dalam model barisan. Untuk tensor yang perlu sering mengakses CPU pada sisi klien, sebaiknya gunakan gabungan memori bersama.
Untuk mendukung fitur domain memori, implementasikan
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 buffer yang diperlukan.BufferRole
menjelaskan 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 tersebut.
Buffer yang dialokasikan bersifat internal untuk driver. {i>Driver<i} dapat memilih lokasi {i>buffer <i}
atau tata letak data mana pun. Saat buffer berhasil dialokasikan, klien driver dapat mereferensikan atau berinteraksi dengan buffer menggunakan token yang ditampilkan atau objek IBuffer
.
Token dari IDevice::allocate
diberikan saat mereferensikan buffer sebagai salah satu objek MemoryPool
dalam struktur Request
eksekusi. Agar proses tidak mencoba mengakses buffer
yang dialokasikan di proses lain, driver harus menerapkan validasi yang tepat pada setiap
penggunaan buffer. Driver harus memvalidasi bahwa penggunaan buffer adalah salah satu
peran BufferRole
yang disediakan selama alokasi dan harus segera menggagalkan eksekusi
jika penggunaannya ilegal.
Objek
IBuffer
digunakan untuk penyalinan memori eksplisit. Dalam situasi tertentu, klien
driver harus melakukan inisialisasi buffer yang dikelola driver dari gabungan memori bersama
atau menyalin buffer keluar ke kumpulan memori bersama. Contoh kasus penggunaan mencakup:
- Inisialisasi tensor status
- Menyimpan hasil menengah dalam cache
- Eksekusi penggantian 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. Mendukung mode non-BLOB
hardware_buffer
bersifat opsional bagi pengemudi.
Selama alokasi buffer, dimensi buffer dapat disimpulkan dari operand model yang sesuai dari semua peran yang ditetapkan oleh BufferRole
, dan dimensi yang disediakan dalam BufferDesc
. Jika semua informasi dimensi digabungkan, buffer mungkin memiliki dimensi atau peringkat yang tidak diketahui. Dalam kasus
tersebut, buffer berada dalam status fleksibel, yaitu dimensi bersifat tetap saat digunakan
sebagai input model dan dalam status dinamis saat digunakan sebagai output model. Buffer yang sama
dapat digunakan dengan berbagai bentuk output dalam eksekusi yang berbeda dan
driver harus menangani perubahan ukuran buffer dengan benar.
Domain memori adalah fitur opsional. Driver dapat menentukan bahwa driver tidak dapat mendukung permintaan alokasi tertentu karena sejumlah alasan. Contoh:
- Buffer yang diminta memiliki ukuran dinamis.
- Driver memiliki batasan memori yang mencegahnya menangani buffer besar.
Beberapa thread yang berbeda dapat membaca dari buffer yang dikelola driver secara serentak. Mengakses buffer secara bersamaan untuk operasi tulis atau baca/tulis tidak ditentukan, tetapi tidak boleh membuat error layanan driver atau memblokir pemanggil tanpa batas. Driver dapat menampilkan error atau membiarkan konten buffer dalam status yang tidak tentu.