XRT 管理のカーネルおよびカーネル引数の設定の際、アクセラレータ カードまたはデバイスのメモリとの間でデータを転送する場合は、作成されたバッファー オブジェクト (xrt::bo
) が使用されます。
通常クラス コンストラクターは、標準の 4K アライメントされたバッファー オブジェクトを割り当てます。次のコードでは、ヒープ メモリ内のユーザー空間によって割り当てられたホスト バッキング ポインターを持つ標準バッファー オブジェクトと、カーネル引数 (krnl.group_id
) に関連付けられたメモリ バンクに割り当てられたデバイス側のバッファーを作成します。xrt::bo
コンストラクター内のオプションのフラグを使用すると、「特殊なバッファーの作成」に示すような特殊な状況で使用する非標準型のバッファーを作成できます。
std::cout << "Allocate Buffer in Global Memory\n";
auto bo0 = xrt::bo(device, vector_size_bytes, krnl.group_id(0));
auto bo1 = xrt::bo(device, vector_size_bytes, krnl.group_id(1));
auto bo_out = xrt::bo(device, vector_size_bytes, krnl.group_id(2));
重要: 現時点では、ホストからグローバル メモリまでのスループットを最大化するために 4 GB を上回るバッファーは使用できませんが、ザイリンクス ではバッファー サイズをできれば少なくとも 2 MB に抑えることをお勧めしています。
バッファーが確立され、データがいっぱいになった状態で、ホストとカーネル間の転送を有効にするには、次のようないくつかの方法があります。
-
xrt::bo::sync()
の使用 - ホストからデバイスに
XCL_BO_SYNC_TO_DEVICE
フラグ付きでデータを同期する場合はxrt::bo::sync
を、デバイスからホストにXCL_BO_SYNC_FROM_DEVICE
フラグ付きでデータを同期する場合はxrt::bo::write
を、ホスト アプリケーションからバッファーを書き込んだり、デバイスからバッファーを読み出す場合はxrt::bo::read
を使用します。bo0.write(buff_data); bo0.sync(XCL_BO_SYNC_BO_TO_DEVICE); bo1.write(buff_data); bo1.sync(XCL_BO_SYNC_BO_TO_DEVICE); ... bo_out.sync(XCL_BO_SYNC_BO_FROM_DEVICE); bo_out.read(buff_data);
注記: ユーザー ポインターからのバッファーの作成に示すように、バッファーがユーザー ポインターを使用して作成される場合、xrt::bo::sync
呼び出しで十分なので、xrt::bo::write
またはxrt::bo::read
コマンドは必要ありません。 -
xrt::bo::map()
の使用 - このメソッドは、ホスト側のバッファー バッキング ポインターをユーザー ポインターにマップできるようにします。
// Map the contents of the buffer object into host memory auto bo0_map = bo0.map<int*>(); auto bo1_map = bo1.map<int*>(); auto bo_out_map = bo_out.map<int*>();
ホスト コードは、データを読み出しおよび書き込み用のユーザー ポインターを連続して実行できます。ただし、マップされたポインターに書き込んだ後 (またはマップされたポインターから読み出す前)、DMA 動作に必要な方向フラグを指定して
xrt::bo::sync()
コマンドを使用する必要があります。for (int i = 0; i < DATA_SIZE; ++i) { bo0_map[i] = i; bo1_map[i] = i; } // Synchronize buffer content with device side bo0.sync(XCL_BO_SYNC_BO_TO_DEVICE); bo1.sync(XCL_BO_SYNC_BO_TO_DEVICE);
その他のバッファーで説明されるように、XRT ネイティブ API では、その他にもサポートされるバッファー タイプと転送シナリオがあります。