Bu sayfada, işlenen tamponları sürücü ve çerçeve arasında verimli bir şekilde iletmek için kullanılan veri yapıları ve yöntemler açıklanmaktadır.
Model derleme zamanında çerçeve, sabit işlenenlerin değerlerini sürücüye sağlar. Sabit işlenenin ömrüne bağlı olarak, değerleri HIDL vektöründe veya paylaşılan bellek havuzunda bulunur.
- Kullanım ömrü
CONSTANT_COPY
ise değerler, model yapısınınoperandValues
alanında bulunur. HIDL vektörindeki değerler işlemler arası iletişim (IPC) sırasında kopyalandığından, bu genellikle skaler işlenenler (örneğin,ADD
içindeki aktivasyon skalerleri) ve küçük tensör parametreleri (örneğin,RESHAPE
içindeki şekil tensörü) gibi az miktarda veriyi tutmak için kullanılır. - Kullanım ömrü
CONSTANT_REFERENCE
ise değerler, model yapısınınpools
alanında bulunur. IPC sırasında ham değerleri kopyalamak yerine, yalnızca paylaşılan bellek havuzlarının tutma yerleri kopyalanır. Bu nedenle, paylaşılan bellek havuzlarını kullanarak büyük miktarda veriyi (örneğin, konvolüsyonlardaki ağırlık parametreleri) saklamak HIDL vektörlerinden daha verimlidir.
Model yürütme zamanında çerçeve, giriş ve çıkış işlenenlerinin tamponlarını sürücüye sağlar. HIDL vektöründe gönderilebilecek derleme süresi sabitlerinden farklı olarak, bir yürütmenin giriş ve çıkış verileri her zaman bir bellek havuzu koleksiyonu aracılığıyla iletilir.
hidl_memory
HIDL veri türü, eşlenmemiş bir paylaşılan bellek havuzunu temsil etmek için hem derleme hem de yürütmede kullanılır. Sürücü, hidl_memory
veri türünün adına göre kullanılabilir hale getirmek için belleği uygun şekilde eşlemelidir.
Desteklenen bellek adları şunlardır:
ashmem
: Android paylaşılan anı. Daha fazla ayrıntı için bellek bölümüne bakın.mmap_fd
:mmap
aracılığıyla bir dosya tanımlayıcı tarafından desteklenen paylaşılan anı.hardware_buffer_blob
:AHARDWARE_BUFFER_FORMAT_BLOB
biçiminde bir ADonanımBuffer tarafından desteklenen paylaşılan bellek. Nöral Ağlar (NN) HAL 1.2'de kullanılabilir. Daha fazla bilgi için ADonanımBuffer'a bakın.hardware_buffer
:AHARDWARE_BUFFER_FORMAT_BLOB
biçimini kullanmayan genel bir A hardwareBuffer tarafından desteklenen paylaşılan bellek. BLOB olmayan mod donanım arabelleği yalnızca model yürütmede desteklenir.NN HAL 1.2 sürümünden kullanılabilir. Daha fazla bilgi için ADonanımBuffer'a bakın.
NNAPI, NN HAL 1.3'ten itibaren sürücü tarafından yönetilen arabellekler için ayırıcı arayüzler sağlayan bellek alan adlarını destekler. Sürücü tarafından yönetilen tamponlar, yürütme girişi veya çıkışı olarak da kullanılabilir. Daha fazla bilgi için Bellek alanları bölümüne bakın.
NNAPI sürücüleri, ashmem
ve mmap_fd
bellek adlarının eşlenmesini desteklemelidir. Sürücüler, NN HAL 1.3 sürümünden itibaren hardware_buffer_blob
eşlemesini de desteklemelidir. BLOB olmayan genel mod hardware_buffer
ve bellek alanları için destek isteğe bağlıdır.
Donanım Arabelleği
ADonanımBuffer, Gralloc arabelleğini sarmalayan paylaşılan bir bellek türüdür. Android 10'da Neural Networks API'si (NNAPI), sürücünün veri kopyalamadan yürütme işlemleri gerçekleştirmesini sağlayarak ADonanımBuffer'ın kullanılmasını destekler. Bu da uygulamaların performansını ve güç tüketimini artırır. Örneğin, bir kamera HAL yığını, kamera NDK ve medya NDK API'leri tarafından oluşturulan ADonanımBuffer tutma yerlerini kullanarak makine öğrenimi iş yükleri için ADonanımBuffer nesnelerini NNAPI'ye iletebilir. Daha fazla bilgi için ANeuralNetworksMemory_createFromAHardwareBuffer
sayfasını inceleyin.
NNAPI'de kullanılan ADonanımBuffer nesneleri, hardware_buffer
veya hardware_buffer_blob
adlı bir hidl_memory
yapısıyla sürücüye iletilir.
hidl_memory
struct hardware_buffer_blob
, yalnızca AHARDWAREBUFFER_FORMAT_BLOB
biçimine sahip ADonanımBuffer nesnelerini temsil eder.
Çerçevenin gerektirdiği bilgiler, hidl_memory
yapısının hidl_handle
alanında kodlanmıştır. hidl_handle
alanı, ADonanımBuffer veya Gralloc arabelleği ile ilgili gerekli tüm meta verileri kodlayan native_handle
öğesini sarmalar.
Sürücü, sağlanan hidl_handle
alanının kodunu düzgün şekilde çözmeli ve hidl_handle
tarafından açıklanan belleğe erişmelidir. getSupportedOperations_1_2
, getSupportedOperations_1_1
veya getSupportedOperations
yöntemi çağrıldığında, sürücünün sağlanan hidl_handle
kodunun kodunu çözüp çözemeyeceğini ve hidl_handle
tarafından açıklanan belleğe erişip erişemeyeceğini algılaması gerekir. Sabit bir işlem gören için kullanılan hidl_handle
alanı desteklenmiyorsa model hazırlığı başarısız olmalıdır. Yürütmenin giriş veya çıkış işleneni için kullanılan hidl_handle
alanı desteklenmiyorsa yürütme başarısız olmalıdır. Model hazırlama veya yürütme işlemi başarısız olursa sürücünün GENERAL_FAILURE
hata kodu döndürmesi önerilir.
Bellek alanları
NNAPI, Android 11 veya sonraki sürümleri çalıştıran cihazlarda sürücü tarafından yönetilen arabellekler için ayırıcı arayüzler sağlayan bellek alanlarını destekler. Bu sayede, yürütmeler arasında cihaz yerel belleklerinin aktarılması sağlanır ve aynı sürücü üzerinde art arda gerçekleştirilen yürütmeler arasında gereksiz veri kopyalama ve dönüşüm işlemi önlenir. Bu akış Şekil 1'de gösterilmektedir.
Şekil 1. Bellek alanlarını kullanan arabellek veri akışı
Bellek alanı özelliği, çoğunlukla sürücünün içinde bulunan ve istemci tarafında sık erişime ihtiyaç duymayan tensörler için tasarlanmıştır. Bu tensörlere örnek olarak dizi modellerindeki durum tensörleri verilebilir. İstemci tarafında sık CPU erişimine ihtiyaç duyan tensörler için paylaşılan bellek havuzlarının kullanılması tercih edilir.
Bellek alanı özelliğini desteklemek için IDevice::allocate
uygulayarak çerçevenin sürücü tarafından yönetilen arabellek tahsisi isteğinde bulunmasına izin verin. Ayırma sırasında çerçeve, tampon için aşağıdaki özellikleri ve kullanım kalıplarını sağlar:
BufferDesc
, arabelleğin gerekli özelliklerini açıklar.BufferRole
, tamponun olası kullanım modelini hazırlanan bir modelin girişi veya çıkışı olarak tanımlar. Tampon ayırma sırasında birden fazla rol belirtilebilir ve ayrılan tampon yalnızca belirtilen roller olarak kullanılabilir.
Ayrılan arabellek, sürücünün kendi içindedir. Sürücü, herhangi bir tampon konumunu
veya veri düzenini seçebilir. Arabellek başarıyla ayrıldığında, sürücünün istemcisi döndürülen jetonu veya IBuffer
nesnesini kullanarak arabelleğe başvurabilir veya arabellekle etkileşim kurabilir.
IDevice::allocate
aracından gelen jeton, arabelleğe bir yürütmenin Request
yapısındaki MemoryPool
nesnelerinden biri olarak referans verildiğinde sağlanır. Bir işlemin başka bir işlemde ayrılan arabelleğe erişmeye çalışmasını önlemek için sürücü, arabelleğin her kullanımında doğru doğrulamayı uygulamalıdır. Sürücü, arabellek kullanımının ayırma sırasında sağlanan BufferRole
rollerinden biri olduğunu doğrulamalı ve kullanım yasa dışıysa yürütme işlemi derhal başarısız olmalıdır.
IBuffer
nesnesi, açık bellek kopyalaması için kullanılır. Bazı durumlarda, sürücünün istemcisinin paylaşılan bir bellek havuzundan sürücü tarafından yönetilen arabelleği başlatması veya arabelleği, paylaşılan bir bellek havuzuna kopyalaması gerekir. Kullanım alanlarına şunlar örnek verilebilir:
- Durum tensörünün başlatılması
- Orta sonuçları önbelleğe alma
- CPU'da yedek yürütme
Bu kullanım alanlarını desteklemek için sürücünün bellek alan adı ayırmayı destekliyorsa IBuffer::copyTo
ve IBuffer::copyFrom
özelliklerini ashmem
, mmap_fd
ve hardware_buffer_blob
ile uygulaması gerekir. Sürücünün BLOB dışı modu desteklemesi isteğe bağlıdır
hardware_buffer
.
Tampon ayırma sırasında tamponun boyutları, BufferRole
tarafından belirtilen tüm rollerin karşılık gelen model işlenenlerinden ve BufferDesc
içinde sağlanan boyutlardan çıkarılabilir. Tüm boyutsal bilgiler birleştirildiğinde tamponun boyutları veya sıralaması bilinmeyen olabilir. Böyle bir durumda tampon, model girişi olarak kullanıldığında boyutların sabit olduğu, model çıkışı olarak kullanıldığında ise dinamik durumda olduğu esnek bir durumda olur. Aynı arabellek, farklı yürütmelerde farklı çıkış şekilleriyle kullanılabilir ve sürücünün arabellek yeniden boyutlandırmayı doğru şekilde işlemesi gerekir.
Bellek alanı, isteğe bağlı bir özelliktir. Sürücü, çeşitli nedenlerden dolayı belirli bir ayırma isteğini destekleyemediğini belirleyebilir. Örnek:
- İstenen arabellek dinamik boyuta sahip.
- Sürücünün, büyük arabellekleri işlemesini engelleyen bellek kısıtlamaları var.
Birkaç farklı iş parçacığının sürücü tarafından yönetilen arabellekten eşzamanlı olarak okunması mümkündür. Yazma veya okuma/yazma için arabelleğe aynı anda erişim tanımlanmamıştır ancak sürücü hizmetini kilitlememeli veya çağrıyı süresiz olarak engellememelidir. Sürücü bir hata döndürebilir veya arabelleğin içeriğini belirsiz bir durumda bırakabilir.