データ転送とカーネル計算のオーバーラップ - 2022.1 日本語

Vitis 統合ソフトウェア プラットフォームの資料: アプリケーション アクセラレーション開発 (UG1393)

Document ID
UG1393
Release Date
2022-05-25
Version
2022.1 日本語

データベース分析のようなアプリケーションでは、アクセラレーション デバイスで使用可能なグローバル デバイス メモリよりも大きなデータ セットが使用され、データ全体をブロック単位で転送して処理する必要があります。これらのアプリケーションで優れたパフォーマンスを達成するには、データ転送と計算をオーバーラップさせる手法が必要となります。

この例は、GitHub の Vitis Accelerated Exampleshost カテゴリにある overlap 例からの vadd カーネルのものです。この例は、アプリケーションでホスト (CPU) と FPGA の計算をオーバーラップさせる手法を示します。カーネルは 2 つの配列をまとめて追加し、出力に書き込んでいます。この例では、ホストで実行する必要のあるタスクは次の 4 つです。

  1. バッファー a の書き込み (Wa)
  2. バッファー b の書き込み (Wb)
  3. vadd カーネルの実行
  4. バッファー c の読み出し (Rc)

データ転送の最適化をせずに単純な順番どおりのコマンド キューを使用すると、実行タイムライン全体のトレースは次のようになります。

図 1. タスクのホスト ビュー

順不同コマンド キューを使用すると、次の図に示すように、データ転送とカーネル実行をオーバーラップできます。この例のホスト コードでは、カーネルが 1 セットのバッファーを処理している間に、ホストでもう 1 つのバッファーのセットを処理できるように、すべてのバッファーにダブル バッファリングが使用されます。

OpenCL event オブジェクトを使用すると、複雑な操作依存を簡単に設定して、ホスト スレッドとデバイス動作を同期できます。イベントは、操作のステータスを調べるための OpenCL オブジェクトです。イベント オブジェクトは、readwrite、およびメモリ オブジェクトの copy コマンドで作成されるか、clCreateUserEvent を使用して作成されたユーザー イベントです。

これらのコマンドで返されるイベントをクエリすることにより、操作が完了したかどうかを確認できます。次の図の矢印は、最適なパフォーマンスを達成するために、イベント トリガーをどのように設定できるかを示しています。

図 2. イベント トリガー設定

例では、ホスト コード ( host.cpp ) は、ループ内の 4 つのタスクをエン キューしてデータ セット全体を処理します。また、各タスクのデータ依存が満たされるように、異なるタスク間のイベント同期を設定します。ダブル バッファリングは、異なるメモリ オブジェクト値を clEnqueueMigrateMemObjects API に渡すことにより設定します。イベント同期は、各 API 呼び出しがほかのイベントを待ち、その API が終了してからそれ自身のイベントをトリガーするようにすると達成できます。

次に示す [Timeline Trace] ビューでは、計算ユニット vadd_1 が継続的に実行されており、データ転送時間は完全に隠されています。

図 3. データ転送時間が隠された [Timeline Trace] ビュー