進行我們的可用性調查以改進此站點。
本頁面由 Cloud Translation API 翻譯而成。
Switch to English

內存池

此頁面描述了用於在驅動程序和框架之間有效地傳遞操作數緩衝區的數據結構和方法。

在模型編譯時,框架將常量操作數的值提供給驅動程序。根據常量操作數的生存期,其值位於HIDL向量或共享內存池中。

  • 如果生存期為CONSTANT_COPY ,則這些值位於模型結構的operandValues字段中。由於HIDL向量中的值是在進程間通信(IPC)期間複製的,因此通常僅用於保存少量數據,例如標量操作數(例如ADD的激活標量)和小張量參數(例如, RESHAPE的形狀張量)。
  • 如果生存期為CONSTANT_REFERENCE ,則這些值位於模型結構的pools字段中。在IPC期間,僅共享內存池的句柄被複製,而不是複制原始值。因此,使用共享內存池比HIDL向量更有效地保存大量數據(例如,卷積中的權重參數)。

在模型執行時,框架將輸入和輸出操作數的緩衝區提供給驅動程序。與可能在HIDL向量中發送的編譯時常量不同,執行的輸入和輸出數據始終通過一組內存池進行通信。

HIDL數據類型hidl_memory在編譯和執行中均用於表示未映射的共享內存池。驅動程序應根據hidl_memory數據類型的名稱相應地映射內存以使其可用。支持的內存名稱是:

  • ashmem :Android共享內存。有關更多詳細信息,請參見memory
  • mmap_fd :通過mmap由文件描述符支持的共享內存。
  • hardware_buffer_blob :由AHardwareBuffer支持的共享內存,格式為AHARDWARE_BUFFER_FORMAT_BLOB 。可從神經網絡(NN)HAL 1.2獲得。有關更多詳細信息,請參見AHardwareBuffer
  • hardware_buffer :由不使用AHARDWARE_BUFFER_FORMAT_BLOB格式的常規AHardwareBuffer支持的共享內存。非BLOB模式硬件緩衝區僅在模型執行中受支持。可從NN HAL 1.2獲得。有關更多詳細信息,請參見AHardwareBuffer

從NN HAL 1.3開始,NNAPI支持為驅動程序管理的緩衝區提供分配器接口的內存域。驅動程序管理的緩衝區也可用作執行輸入或輸出。有關更多詳細信息,請參見內存域

NNAPI驅動程序必須支持ashmemmmap_fd內存名稱的映射。從NN HAL 1.3開始,驅動程序還必須支持hardware_buffer_blob映射。對常規的非BLOB模式的hardware_buffer和內存域的支持是可選的。

硬件緩衝區

AHardwareBuffer是包裝Gralloc緩衝區的一種共享內存。在Android 10中,神經網絡API(NNAPI)支持使用AHardwareBuffer ,使驅動程序無需複制數據即可執行執行,從而提高了應用程序的性能和功耗。例如,攝像機HAL堆棧可以使用攝像機NDK和媒體NDK API生成的AHardwareBuffer句柄將AHardwareBuffer對像傳遞給NNAPI,以進行機器學習工作負載。有關更多信息,請參見ANeuralNetworksMemory_createFromAHardwareBuffer

NNAPI中使用的AHardwareBuffer對象通過名為hardware_bufferhardware_buffer_blobhidl_memory結構傳遞給驅動程序。 hidl_memory結構hardware_buffer_blob僅表示AHARDWAREBUFFER_FORMAT_BLOB格式的AHardwareBuffer對象。

框架所需的信息被編碼在hidl_memory結構的hidl_handle字段中。 hidl_handle字段包裝native_handle ,它對AHardwareBuffer或Gralloc緩衝區的所有必需元數據進行編碼。

驅動程序必須正確解碼提供的hidl_handle字段,並訪問hidl_handle描述的內存。當調用getSupportedOperations_1_2getSupportedOperations_1_1getSupportedOperations方法時,驅動程序應檢測它是否可以解碼提供的hidl_handle並訪問hidl_handle描述的內存。如果不支持用於常量操作數的hidl_handle字段,則模型準備必須失敗。如果不支持用於執行的輸入或輸出操作數的hidl_handle字段,則執行必須失敗。如果模型準備或執行失敗,建議驅動程序返回GENERAL_FAILURE錯誤代碼。

記憶域

對於運行Android 11或更高版本的設備,NNAPI支持為驅動程序管理的緩衝區提供分配器接口的內存域。這允許在執行之間傳遞設備本機內存,從而抑制了不必要的數據複製以及同一驅動程序上連續執行之間的轉換。此流程如圖1所示。

帶和不帶內存域的緩衝區數據流
圖1.使用內存域的緩衝區數據流

內存域功能主要用於驅動程序內部的張量,並且不需要在客戶端頻繁訪問。這種張量的示例包括序列模型中的狀態張量。對於需要在客戶端頻繁訪問CPU的張量,最好使用共享內存池。

要支持內存域功能,請實現IDevice::allocate以允許框架請求驅動程序管理的緩衝區分配。在分配期間,框架為緩衝區提供以下屬性和使用模式:

  • BufferDesc描述了緩衝區的必需屬性。
  • BufferRole將緩衝區的潛在使用模式描述為準備好的模型的輸入或輸出。在緩衝區分配期間可以指定多個角色,並且分配的緩衝區只能用作那些指定的角色。

分配的緩衝區在驅動程序內部。驅動程序可以選擇任何緩衝區位置或數據佈局。成功分配緩衝區後,驅動程序的客戶端可以使用返回的令牌或IBuffer對象引用緩衝區或與緩衝區進行交互。

當將緩衝區引用為執行的Request結構中的MemoryPool對象之一時,將提供IDevice::allocate的標記。為了防止某個進程嘗試訪問在另一個進程中分配的緩衝區,驅動程序必須在每次使用緩衝區時應用正確的驗證。驅動程序必須確認緩衝區使用情況是分配過程中提供的BufferRole角色之一,並且如果使用不合法,則必須立即使執行失敗。

IBuffer像用於顯式內存複製。在某些情況下,驅動程序的客戶端必須從共享內存池初始化驅動程序管理的緩衝區,或者將緩衝區復製到共享內存池中。用例示例包括:

  • 狀態張量的初始化
  • 緩存中間結果
  • 在CPU上執行後備廣告

為了支持這些用例,如果驅動程序支持內存域分配,則必須使用ashmemmmap_fdhardware_buffer_blob實現IBuffer::copyToIBuffer::copyFrom 。驅動程序支持非BLOB模式hardware_buffer是可選的。

在緩衝區分配期間,可以從BufferRole指定的所有角色的相應模型操作數以及BufferRole提供的尺寸中BufferDesc的尺寸。合併所有維度信息後,緩衝區可能具有未知的維度或等級。在這種情況下,緩衝器處於靈活狀態,其中,當用作模型輸入時,尺寸是固定的;而當用作模型輸出時,則處於動態狀態。相同的緩衝區可以在不同的執行中與不同形狀的輸出一起使用,並且驅動程序必須正確處理緩衝區的大小。

內存域是一項可選功能。出於多種原因,驅動程序可以確定它不支持給定的分配請求。例如:

  • 請求的緩衝區具有動態大小。
  • 該驅動程序具有內存限制,使其無法處理大緩衝區。

幾個不同的線程有可能同時從驅動程序管理的緩衝區中讀取。同時訪問緩衝區以進行寫或讀/寫操作是不確定的,但是它一定不能使驅動程序服務崩潰或無限期地阻止調用者。驅動程序可以返回錯誤或使緩衝區的內容處於不確定狀態。