Kumpulan memori

Halaman ini menjelaskan struktur data dan metode yang digunakan untuk mengomunikasikan buffer operan secara efisien antara driver dan kerangka kerja.

Pada waktu kompilasi model, kerangka kerja memberikan nilai operan konstan kepada 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 bidang operandValues ​​pada struktur model. Karena nilai dalam vektor HIDL disalin selama komunikasi antarproses (IPC), ini biasanya hanya digunakan untuk menampung sejumlah kecil data seperti operan skalar (misalnya, skalar aktivasi di ADD ) dan parameter tensor kecil (misalnya, tensor bentuk di RESHAPE ).
  • Jika masa pakainya adalah CONSTANT_REFERENCE , nilainya terletak di bidang pools struktur model. Hanya pegangan kumpulan memori bersama yang diduplikasi selama IPC daripada menyalin nilai mentah. Oleh karena itu, menyimpan data dalam jumlah besar (misalnya, parameter bobot dalam konvolusi) akan lebih efisien menggunakan kumpulan memori bersama daripada vektor HIDL.

Pada waktu eksekusi model, kerangka kerja menyediakan buffer operan input dan output ke driver. Berbeda dengan 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 hidl_memory digunakan dalam kompilasi dan eksekusi untuk mewakili kumpulan memori bersama yang belum dipetakan. Pengemudi harus memetakan memori yang sesuai agar 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 melalui mmap .
  • hardware_buffer_blob : Memori bersama yang didukung oleh AHardwareBuffer dengan format AHARDWARE_BUFFER_FORMAT_BLOB . Tersedia dari Jaringan Syaraf Tiruan (NN) HAL 1.2. Untuk detail selengkapnya, lihat AHardwareBuffer .
  • hardware_buffer : Memori bersama yang didukung oleh AHardwareBuffer umum yang tidak menggunakan format AHARDWARE_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 .

Mulai 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 . Mulai 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.

APerangkat KerasBuffer

AHardwareBuffer adalah jenis memori bersama yang membungkus buffer Gralloc . Di Android 10, Neural Networks API (NNAPI) mendukung penggunaan AHardwareBuffer , memungkinkan driver melakukan eksekusi tanpa menyalin data, sehingga meningkatkan performa 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 di NNAPI diteruskan ke driver melalui struct hidl_memory yang diberi nama hardware_buffer atau hardware_buffer_blob . Struct hidl_memory 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 memecahkan kode bidang hidl_handle yang disediakan dengan benar 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 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. Pengemudi disarankan untuk mengembalikan kode kesalahan GENERAL_FAILURE jika persiapan atau eksekusi model 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 meneruskan memori asli perangkat di seluruh eksekusi, menekan penyalinan dan transformasi data yang tidak perlu antara eksekusi berturut-turut pada driver yang sama. Alur ini diilustrasikan pada Gambar 1.

Buffer aliran data dengan dan tanpa domain memori

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 sering di sisi klien. Contoh tensor tersebut mencakup tensor keadaan dalam model urutan. Untuk tensor yang sering memerlukan akses CPU di sisi klien, sebaiknya gunakan kumpulan memori bersama.

Untuk mendukung fitur domain memori, implementasikan IDevice::allocate untuk memungkinkan kerangka kerja meminta alokasi buffer yang dikelola driver. Selama alokasi, kerangka kerja 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 pada 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 eksekusi. Untuk mencegah suatu 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 menggagalkan eksekusi jika penggunaannya ilegal.

Objek IBuffer digunakan untuk penyalinan memori eksplisit. Dalam situasi tertentu, klien driver harus menginisialisasi buffer yang dikelola driver dari kumpulan memori bersama atau menyalin buffer ke kumpulan memori bersama. Contoh kasus penggunaan meliputi:

  • Inisialisasi tensor keadaan
  • Menyimpan hasil antara
  • Eksekusi fallback 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. Driver bersifat opsional untuk mendukung mode non-BLOB hardware_buffer .

Selama alokasi buffer, dimensi buffer dapat disimpulkan dari operan model terkait dari semua peran yang ditentukan oleh BufferRole , dan dimensi yang disediakan dalam BufferDesc . Dengan menggabungkan semua informasi dimensi, buffer mungkin memiliki dimensi atau peringkat yang tidak diketahui. Dalam kasus seperti ini, buffer berada dalam keadaan fleksibel dimana dimensinya tetap ketika digunakan sebagai masukan model dan dalam keadaan dinamis ketika digunakan sebagai keluaran model. Buffer yang sama dapat digunakan dengan bentuk output berbeda dalam eksekusi berbeda dan driver harus menangani pengubahan ukuran buffer dengan benar.

Domain memori adalah fitur opsional. Pengemudi dapat menentukan bahwa ia tidak dapat mendukung permintaan alokasi tertentu karena sejumlah alasan. Misalnya:

  • Buffer yang diminta memiliki ukuran dinamis.
  • Pengemudi memiliki keterbatasan memori yang mencegahnya menangani buffer yang besar.

Beberapa thread berbeda dapat membaca dari buffer yang dikelola driver secara bersamaan. Mengakses buffer secara bersamaan untuk menulis atau membaca/menulis tidak ditentukan, tetapi tidak boleh membuat layanan driver crash atau memblokir pemanggil tanpa batas waktu. Pengemudi dapat mengembalikan kesalahan atau membiarkan konten buffer dalam keadaan tidak menentu.