Google berkomitmen untuk mendorong terwujudnya keadilan ras bagi komunitas Kulit Hitam. Lihat caranya.

Pools Memori

Halaman ini menjelaskan struktur data dan metode yang digunakan untuk mengkomunikasikan buffer operan 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 pakai CONSTANT_COPY , nilai terletak di bidang operandValues 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 di ADD ) dan parameter tensor kecil (misalnya, bentuk tensor di RESHAPE ).
  • Jika masa pakai CONSTANT_REFERENCE , nilai ditempatkan di bidang pools 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 dari operan input dan output ke driver. Tidak seperti konstanta waktu kompilasi yang mungkin dikirim dalam vektor HIDL, data masukan dan keluaran dari suatu eksekusi selalu dikomunikasikan melalui kumpulan kumpulan memori.

Tipe data hidl_memory digunakan baik dalam kompilasi maupun eksekusi untuk mewakili kumpulan memori bersama yang belum dipetakan. Pengemudi harus memetakan memori yang sesuai agar dapat digunakan berdasarkan nama hidl_memory data hidl_memory . Nama memori yang didukung adalah:

  • ashmem : Android berbagi memori. 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 Neural Networks (NN) HAL 1.2. Untuk lebih jelasnya, 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 lebih jelasnya, 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 ashmem dan mmap_fd nama memori. Dari NN HAL 1.3, driver juga harus mendukung pemetaan hardware_buffer_blob . Dukungan untuk mode umum non-BLOB hardware_buffer dan domain memori bersifat opsional.

AHardwareBuffer

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, yang meningkatkan performa dan konsumsi daya untuk aplikasi. Misalnya, tumpukan HAL kamera dapat meneruskan objek AHardwareBuffer ke NNAPI untuk beban kerja machine learning 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 bernama hardware_buffer atau hardware_buffer_blob . hidl_memory hardware_buffer_blob hidl_memory hanya mewakili objek AHardwareBuffer dengan format AHARDWAREBUFFER_FORMAT_BLOB .

Informasi yang diperlukan oleh framework dikodekan di bidang hidl_handle dari struct hidl_memory . Kolom hidl_handle membungkus native_handle , yang native_handle semua metadata yang diperlukan tentang buffer AHardwareBuffer atau Gralloc.

Pengemudi harus benar-benar memecahkan kode bidang hidl_handle disediakan dan mengakses memori yang dijelaskan oleh hidl_handle . Saat metode getSupportedOperations_1_2 , getSupportedOperations_1_1 , atau getSupportedOperations dipanggil, driver harus mendeteksi apakah ia dapat mendekode hidl_handle disediakan dan mengakses memori yang dijelaskan oleh hidl_handle . Persiapan model harus gagal jika bidang hidl_handle digunakan untuk operan konstan tidak didukung. Eksekusi harus gagal jika bidang hidl_handle digunakan untuk operan input atau output dari eksekusi tidak didukung. Disarankan bagi pengemudi 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 yang berurutan pada driver yang sama. Aliran ini diilustrasikan pada Gambar 1.

Aliran data buffer dengan dan tanpa domain memori
Gambar 1. Aliran data buffer menggunakan domain memori

Fitur domain memori ditujukan untuk tensor yang sebagian besar bersifat internal untuk driver dan tidak memerlukan akses sering di sisi klien. Contoh tensor semacam itu termasuk tensor keadaan dalam model sekuens. Untuk tensor yang sering membutuhkan akses CPU di sisi klien, sebaiknya gunakan kumpulan memori bersama.

Untuk mendukung fitur domain memori, implementasikan IDevice::allocate untuk mengizinkan kerangka kerja meminta alokasi buffer yang dikelola driver. Selama alokasi, framework menyediakan properti dan pola penggunaan berikut untuk buffer:

  • BufferDesc menjelaskan properti buffer yang diperlukan.
  • BufferRole mendeskripsikan pola penggunaan potensial dari 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. Seorang pengemudi dapat memilih lokasi buffer atau tata letak data apa pun. Ketika buffer berhasil dialokasikan, klien dari 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 sebuah 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 disediakan selama alokasi dan harus segera gagal eksekusi jika penggunaannya ilegal.

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

  • Inisialisasi tensor status
  • Menyimpan hasil menengah
  • 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. 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 ditetapkan saat digunakan sebagai masukan model dan dalam keadaan dinamis saat digunakan sebagai keluaran 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. Seorang pengemudi dapat menentukan bahwa ia 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 yang besar.

Ada kemungkinan beberapa utas berbeda membaca dari buffer yang dikelola driver secara bersamaan. Mengakses buffer secara bersamaan untuk menulis atau membaca / menulis tidak ditentukan, tetapi itu tidak boleh merusak layanan driver atau memblokir pemanggil tanpa batas. Pengemudi dapat mengembalikan kesalahan atau membiarkan konten buffer dalam keadaan tidak pasti.