Google は、黒人コミュニティに対する人種平等の促進に取り組んでいます。取り組みを見る
このページは 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共有メモリ。詳細については、メモリを参照してください。
  • mmap_fdmmap介してファイル記述子でバックアップされた共有メモリ。
  • hardware_buffer_blob :AHARDWARE_BUFFER_FORMAT_BLOB形式のAHARDWARE_BUFFER_FORMAT_BLOBによってバックアップされた共有メモリ。 Neural Networks(NN)HAL1.2から入手できます。詳細については、 AHardwareBufferを参照してください。
  • hardware_buffer :フォーマットAHARDWARE_BUFFER_FORMAT_BLOB使用しない一般的なAHardwareBufferによってバックアップされる共有メモリ。非BLOBモードのハードウェアバッファは、モデルの実行でのみサポートされます。NNHAL1.2から利用できます。詳細については、 AHardwareBufferを参照してください。

NN HAL 1.3以降、NNAPIは、ドライバー管理バッファーのアロケーターインターフェイスを提供するメモリドメインをサポートします。ドライバ管理のバッファは、実行の入力または出力としても使用できます。詳細については、メモリドメインを参照してください。

NNAPIドライバーは、 ashmemおよびmmap_fdメモリ名のマッピングをサポートする必要があります。 NN HAL 1.3以降、ドライバーはhardware_buffer_blobマッピングもサポートする必要がありhardware_buffer_blob 。一般的な非BLOBモードのhardware_bufferおよびメモリドメインのサポートはオプションです。

AHardwareBuffer

AHardwareBufferは、 Grallocバッファーをラップする共有メモリの一種です。 Android 10では、Neural Networks API(NNAPI)がAHardwareBufferの使用をサポートしているため、ドライバーはデータをコピーせずに実行できるため、アプリのパフォーマンスと消費電力が向上します。たとえば、カメラHALスタックは、カメラNDKおよびメディアNDK APIによって生成されたAHardwareBufferハンドルを使用して、マシン学習ワークロード用にAHardwareBufferオブジェクトをNNAPIに渡すことができます。詳細については、 ANeuralNetworksMemory_createFromAHardwareBuffer参照してください。

NNAPIで使用されるAHardwareBufferオブジェクトは、 hardware_bufferまたはhardware_buffer_blobという名前のhidl_memory構造を介してドライバーに渡されhardware_buffer_blobhidl_memory構造のhardware_buffer_blobは、 AHARDWAREBUFFER_FORMAT_BLOB形式のAHardwareBufferオブジェクトのみを表します。

フレームワークに必要な情報は、 hidl_memory構造のhidl_handleフィールドにエンコードされます。 hidl_handleフィールドはhidl_handleラップしnative_handle 。これは、AHardwareBufferまたはGrallocバッファーに関する必要なすべてのメタデータをエンコードします。

ドライバが適切に提供される復号しなければならないhidl_handleフィールドとアクセスによって説明したメモリhidl_handle 。場合getSupportedOperations_1_2getSupportedOperations_1_1 、又はgetSupportedOperationsメソッドが呼び出され、運転者は、それが提供デコードできるかどうかを検出する必要がありhidl_handleとアクセスによって説明したメモリhidl_handle 。定数オペランドに使用されるhidl_handleフィールドがサポートされていない場合、モデルの準備は失敗する必要があります。実行の入力または出力オペランドに使用されるhidl_handleフィールドがhidl_handleされていない場合、実行は失敗する必要があります。モデルの準備または実行が失敗した場合、ドライバーはGENERAL_FAILUREエラーコードを返すことをお勧めします。

メモリドメイン

Android 11以降を実行しているデバイスの場合、NNAPIは、ドライバー管理バッファーのアロケーターインターフェイスを提供するメモリドメインをサポートします。これにより、実行間でデバイスのネイティブメモリを渡すことができ、同じドライバでの連続した実行間の不要なデータのコピーと変換を抑制できます。このフローを図1に示します。

メモリドメインがある場合とない場合のバッファデータフロー
図1.メモリドメインを使用したバッファデータフロー

メモリドメイン機能は、ほとんどがドライバーの内部にあり、クライアント側で頻繁にアクセスする必要のないテンサーを対象としています。このようなテンサーの例には、シーケンスモデルの状態テンサーが含まれます。クライアント側で頻繁にCPUアクセスを必要とするテンサーの場合、共有メモリプールを使用することをお勧めします。

メモリドメイン機能をサポートするには、 IDevice::allocate実装して、フレームワークがドライバー管理のバッファー割り当てを要求できるようにします。割り当て中に、フレームワークはバッファに次のプロパティと使用パターンを提供します。

  • BufferDescは、バッファーに必要なプロパティを記述します。
  • BufferRoleは、準備されたモデルの入力または出力として、バッファーの潜在的な使用パターンを記述します。バッファの割り当て中に複数の役割を指定でき、割り当てられたバッファは指定された役割としてのみ使用できます。

割り当てられたバッファはドライバの内部にあります。ドライバーは、任意のバッファー位置またはデータレイアウトを選択できます。バッファが正常に割り当てられると、ドライバのクライアントは、返されたトークンまたはIBufferオブジェクトを使用して、バッファを参照または操作できます。

IDevice::allocateからのトークンは、実行のRequest構造でMemoryPoolオブジェクトの1つとしてバッファーを参照するときに提供されます。プロセスが別のプロセスに割り当てられたバッファーにアクセスしようとするのを防ぐために、ドライバーはバッファーを使用するたびに適切な検証を適用する必要があります。ドライバーは、バッファーの使用が割り当て中に提供されたBufferRoleロールの1つであることを検証する必要があり、使用が違法である場合はすぐに実行に失敗する必要があります。

IBufferオブジェクトは、明示的なメモリコピーに使用されます。特定の状況では、ドライバーのクライアントは、共有メモリプールからドライバー管理バッファーを初期化するか、バッファーを共有メモリプールにコピーする必要があります。使用例は次のとおりです。

  • 状態テンソルの初期化
  • 中間結果のキャッシュ
  • CPUでのフォールバック実行

これらのユースケースをサポートするために、ドライバが実装しなければなりませんIBuffer::copyToIBuffer::copyFromしてashmemmmap_fd 、およびhardware_buffer_blobそれはメモリ領域の割り当てをサポートしている場合。ドライバーが非BLOBモードのhardware_bufferをサポートすることはオプションです。

バッファ割り当ての際に、バッファの大きさは、で指定されたすべてのロールの対応するモデルオペランドから推定することができるBufferRole 、及びに設け寸法BufferDesc 。すべての次元情報を組み合わせると、バッファーの次元またはランクが不明になる可能性があります。このような場合、バッファは柔軟な状態にあり、モデル入力として使用されると寸法が固定され、モデル出力として使用されると動的状態になります。同じバッファーをさまざまな実行でさまざまな形状の出力で使用でき、ドライバーはバッファーのサイズ変更を適切に処理する必要があります。

メモリドメインはオプション機能です。ドライバーは、いくつかの理由で、特定の割り当て要求をサポートできないと判断できます。例えば:

  • 要求されたバッファは動的サイズです。
  • ドライバにはメモリの制約があり、大きなバッファを処理できません。

複数の異なるスレッドがドライバー管理バッファーから同時に読み取る可能性があります。書き込みまたは読み取り/書き込みのために同時にバッファにアクセスすることは定義されていませんが、ドライバサービスをクラッシュさせたり、呼び出し元を無期限にブロックしたりしてはなりません。ドライバーはエラーを返すか、バッファーの内容を不確定な状態のままにすることができます。