Bellek havuzları

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ın operandValues 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ın pools 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_memorystruct 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.

Bellek alanları ile ve bellek alanları olmadan arabellek veri akışı

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