Bellek havuzları

Bu sayfada, sürücü ile çerçeve arasında operatör arabelleklerini verimli bir şekilde iletmek için kullanılan veri yapıları ve yöntemler açıklanmaktadır.

Çerçeve, model derleme sırasında sürücüye sabit operatörlerin değerlerini 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ın operandValues alanında bulunur. HIDL vektöründeki değerler, işlemler arası iletişim (IPC) sırasında kopyalandığından bu vektör genellikle yalnızca skaler operatörler (ör. ADD'teki etkinleştirme skaleri) ve küçük tenör parametreleri (ör. RESHAPE'teki şekil tenörü) gibi az miktarda veri tutmak için kullanılır.
  • Ömür CONSTANT_REFERENCE ise değerler, model yapısının pools alanında bulunur. Ham değerlerin kopyalanmak yerine IPC sırasında yalnızca paylaşılan bellek havuzlarının tutamaçlarının kopyalanması 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 bilgi için bellek bölümüne bakın.
  • mmap_fd: mmap aracılığıyla dosya tanımlayıcısıyla desteklenen paylaşılan bellek.
  • hardware_buffer_blob: AHARDWARE_BUFFER_FORMAT_BLOB biçiminde bir AHardwareBuffer tarafından desteklenen paylaşılan bellek. Neural Networks (NN) HAL 1.2'den itibaren 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 moddaki donanım arabelleği yalnızca model yürütmede desteklenir.NN HAL 1.2'den itibaren kullanılabilir. Daha fazla bilgi için AHardwareBuffer başlıklı makaleyi inceleyin.

NN HAL 1.3'ten itibaren NNAPI, sürücü tarafından yönetilen tamponlar için ayırıcı arayüzleri sağlayan bellek alanlarını destekler. Sürücü tarafından yönetilen arabellekler, yürütme girişleri veya çıkışları olarak da kullanılabilir. Ayrıntılı bilgi için Bellek alanları başlıklı makaleyi inceleyin.

NNAPI sürücüleri, ashmem ve mmap_fd bellek adlarının eşlenmesini desteklemelidir. NN HAL 1.3'ten itibaren sürücüler hardware_buffer_blob eşlemesini de desteklemelidir. Genel BLOB dışı mod hardware_buffer ve bellek alanları için destek isteğe bağlıdır.

AHardwareBuffer

AHardwareBuffer, bir Gralloc arabelleğini sarmalayan bir tür paylaşılan bellektir. 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 AHardwareBuffer tutamaçlarını kullanarak makine öğrenimi iş yükleri için AHardwareBuffer nesnelerini NNAPI'ye iletebilir. Daha fazla bilgi için ANeuralNetworksMemory_createFromAHardwareBuffer başlıklı makaleyi 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çimindeki AHardwareBuffer nesnelerini temsil eder.

Çerçevenin gerektirdiği bilgiler, hidl_memory yapısının hidl_handle alanında kodlanmıştır. hidl_handle alanı, AHardwareBuffer veya Gralloc arabelleğiyle ilgili gerekli tüm meta verileri kodlayan native_handle alanını sarar.

Sürücü, sağlanan hidl_handle alanının kodunu doğru ş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ü, sağlanan hidl_handle değerinin kodunu çözüp çözemeyeceğini ve hidl_handle tarafından açıklanan belleğe erişip erişemeyeceğini algılamalıdır. Sabit bir operatör için kullanılan hidl_handle alanı desteklenmiyorsa model hazırlama işlemi başarısız olur. 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 başarısız olursa sürücünün GENERAL_FAILURE hata kodu döndürmesi önerilir.

Anı alanları

Android 11 veya sonraki sürümleri çalıştıran cihazlarda NNAPI, sürücü tarafından yönetilen arabellekler için ayırıcı arayüzleri sağlayan bellek alanlarını destekler. Bu sayede, cihazın yerel bellekleri yürütmeler arasında aktarılabilir. Böylece aynı sürücüdeki art arda yürütmeler arasında gereksiz veri kopyalama ve dönüştürme işlemleri engellenir. Bu akış Şekil 1'de gösterilmektedir.

Bellek alanları olan ve olmayan arabellek veri akışı

Şekil 1. Bellek alanlarını kullanarak veri akışını arabelleğe alma

Bellek alanı özelliği, çoğunlukla sürücüye dahil olan ve istemci tarafında sık sık erişilmesi gerekmeyen tenzorlar için tasarlanmıştır. Bu tür tensörlere örnek olarak sıralı modellerdeki durum tensörleri verilebilir. İstemci tarafında sık sık CPU erişimi gerektiren tenzorlar için paylaşılan bellek havuzları kullanılması tercih edilir.

Bellek alanı özelliğini desteklemek için çerçevenin sürücü tarafından yönetilen arabellek ayırma isteğinde bulunmasına izin vermek üzere IDevice::allocate uygulayın. Framework, atama sırasında arabellek için aşağıdaki özellikleri ve kullanım kalıplarını sağlar:

  • BufferDesc, arabelleğin gerekli özelliklerini açıklar.
  • BufferRole, hazırlanmış bir modelin girişi veya çıkışı olarak arabelleğin olası kullanım şeklini tanımlar. Arabellek ayırma sırasında birden fazla rol belirtilebilir ve ayrılan arabellek yalnızca belirtilen rollerde kullanılabilir.

Ayrılan arabellek sürücü içindedir. Sürücü, herhangi bir arabellek 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ği referans alabilir ya da arabellekle etkileşim kurabilir.

IDevice::allocate kaynağından alınan 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ünün, arabelleğin her kullanımında uygun doğrulamayı uygulaması gerekir. Sürücü, arabellek kullanımının, tahsis sırasında sağlanan BufferRole rollerinden biri olduğunu doğrulamalı ve kullanım yasa dışıysa yürütmeyi hemen iptal etmelidir.

IBuffer nesnesi, açık bellek kopyalaması için kullanılır. Belirli durumlarda, sürücünün istemcisi, sürücü tarafından yönetilen arabelleği paylaşılan bir bellek havuzundan başlatmalı veya arabelleği paylaşılan bir bellek havuzuna kopyalamalıdır. Kullanım alanlarına şunlar örnek verilebilir:

  • Durum tenzorunun başlatılması
  • Ara 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ı tahsisini destekliyorsa ashmem, mmap_fd ve hardware_buffer_blob ile IBuffer::copyTo ve IBuffer::copyFrom özelliklerini uygulaması gerekir. Sürücünün BLOB olmayan modu desteklemesi isteğe bağlıdırhardware_buffer.

Arabellek ayırma sırasında, arabelleğin boyutları BufferRole tarafından belirtilen tüm rollerin ilgili model operatörlerinden ve BufferDesc içinde sağlanan boyutlardan çıkarılabilir. Tüm boyut bilgilerinin birleştirilmesiyle arabellek, bilinmeyen boyutlara veya sıralamaya sahip 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ü, arabelleğin yeniden boyutlandırılmasını düzgün şekilde yapmalıdır.

Bellek alanı, isteğe bağlı bir özelliktir. Sürücü, belirli bir tahsis isteğini çeşitli nedenlerle destekleyemeyeceğini belirleyebilir. Örnek:

  • İstenen arabellek dinamik boyuta sahip.
  • Sürücü, büyük arabellekleri işlemesini engelleyen bellek kısıtlamalarına sahiptir.

Sürücü tarafından yönetilen arabellekten aynı anda birden fazla farklı iş parçacığı okuma yapabilir. Yazma veya okuma/yazma için arabelleğe aynı anda erişmek tanımlanmamıştır ancak sürücü hizmetini kilitlememeli veya arayanı süresiz olarak engellememelidir. Sürücü bir hata döndürebilir veya arabelleğin içeriğini belirsiz durumda bırakabilir.