ハードウェア アクセラレーション チュートリアル

xilinx.com の Vitis™ 開発環境を参照

複数の計算ユニットの使用

バージョン: Vitis 2022.1

入門チュートリアル

このチュートリアルでは、FPGA 上のカーネル インスタンスの数を増やすための柔軟なカーネル リンク プロセスを示します。カーネルの各インスタンスは、計算ユニット (CU) とも呼ばれます。CU 数を増加するこのプロセスを使用すると、統合されたホスト/カーネル システムの並列処理が向上します。

チュートリアルの概要

Vitis™ コア開発キットでは、デフォルトでカーネルごとに CU が 1 つずつ作成されます。ホスト プログラムは、異なるデータ セットに対して同じカーネルを複数回使用できます。この場合、カーネルに対して複数の CU を生成して、これらの CU を同時実行すると、システム全体のパフォーマンスを向上できます。

詳細は、『Vitis 統合ソフトウェア プラットフォームの資料』 (UG1416) のアプリケーション アクセラレーション開発フローの複数のカーネル インスタンスの作成を参照してください。

このチュートリアルでは、次を実行します。

  1. ハードウェア エミュレーションを実行し、エミュレーション レポートを参照して、カーネルが順に複数回実行されることを確認します。

  2. コマンドを順不同に実行できるようにホスト コードを変更します。

  3. カーネル リンク プロセスを変更し、同じカーネルの CU を複数作成します。

  4. ハードウェア エミュレーションを再実行し、CU が同時実行されることを確認します。

このチュートリアルでは、画像フィルター例を使用して複数 CU の利点を示します。このチュートリアルでは、デザインをシンプルにするために、ホスト アプリケーションは実画像ではなく、ランダム データを画素に使用します。デフォルトでは、FPGA にはカーネルの CU が 1 つしか含まれないので、これら 3 つのカーネルは同じハードウェア リソースを使用して順次実行されます。このチュートリアルでは、CU の数を増加し、このカーネルを並列実行する方法を示します。

ホスト コードの OpenCV バージョンは、ソース コード ディレクトリ src/host/host_opencv.cpp でも提供されていますが、このチュートリアルでは OpenCV バージョンを使用する方法は説明しません。ホスト コードの OpenCV バージョンは、OpenCV ライブラリをインストールし、Makefile で OpenCV の設定に関連する必要な変更をした後に使用できます。

開始前の確認事項

このチュートリアルでは、次を使用します。

  • BASH Linux シェル コマンド

  • 2022.1 Vitis コア開発キット リリースおよび xilinx_u200_gen3x16_xdma_2_202110_1 プラットフォーム。必要であれば、ほかのバージョンおよびプラットフォームを使用するように変更することもできます。

重要:

  • 例を実行する前に、『Vitis 統合ソフトウェア プラットフォームの資料』 (UG1416) のアプリケーション アクセラレーション開発フローのインストールの手順に従って、Vitis コア開発キットをインストールしておく必要があります。

  • ザイリンクス Alveo™ データセンター アクセラレータ カードでアプリケーションを実行する場合は、Alveo ポートフォリオ ページの手順に従って、カードとソフトウェア ドライバーを正しくインストールしてください。

チュートリアル リファレンス ファイルの入手

  1. リファレンス ファイルを入手するには、ターミナルに git clone http://github.com/Xilinx/Vitis-Tutorials と入力します。

  2. Hardware_Acceleration/Feature_Tutorials/05-using-multiple-cu ディレクトリに移動し、reference-files ディレクトリにアクセスします。

makefile フロー

このチュートリアルで使用する makefile は、reference-files/Makefile に含まれます。最上位設定には、次が含まれます。

  • VPP: カーネル コードをコンパイルする Vitis コンパイラ パス。

  • EMCONFIGUTIL: エミュレーション コンフィギュレーション ファイル emconfig.json を作成するユーティリティのパス。

  • DEVICE: ターゲット プラットフォーム。

  • EXE_OPT: コマンド ライン引数として渡されるランタイム オプション: コンパイル済みカーネル xclbin ファイル。

ハードウェア エミュレーションの実行

次のコマンドでハードウェア エミュレーションを実行します。

make run TARGET=hw_emu

ハードウェア エミュレーション (hw_emu) では、カーネル コードはハードウェア モデル (RTL) にコンパイルされ、ハードウェア シミュレータで実行されますが、システムの残りの部分には C シミュレータが使用されます。ビルドおよび実行にかかる時間は長くなりますが、詳細でサイクル精度のカーネル アクティビティが表示されます。このターゲットは、FPGA で実行されるロジックの機能をテストして、初期パフォーマンス見積もりを取得する場合に便利です。

注記: ホスト ソフトウェアおよびハードウェアのビルド方法は、Vitis 入門チュートリアルを参照してください。

ホスト コードの確認

  1. エミュレーション run を実行中、別のターミナルで src/host/host.cpp ファイルを開きます。

  2. 234 ~ 236 行目を確認します。Y、U、および V チャネルを処理するためにフィルター関数が 3 回呼び出されています。

    request[xx*3+0] = Filter(coeff.data(), y_src.data(), width, height, stride, y_dst.data());
    request[xx*3+1] = Filter(coeff.data(), u_src.data(), width, height, stride, u_dst.data());
    request[xx*3+2] = Filter(coeff.data(), v_src.data(), width, height, stride, v_dst.data());
    

    この関数は、78 行目から記述されています。次の抜粋部分で、カーネル引数が設定され、カーネルが clEnqueueTask コマンドにより実行されます。

     // Set the kernel arguments
     clSetKernelArg(mKernel, 0, sizeof(cl_mem),       &mSrcBuf[0]);
     clSetKernelArg(mKernel, 1, sizeof(cl_mem),       &mSrcBuf[1]);
     clSetKernelArg(mKernel, 2, sizeof(unsigned int), &width);
     clSetKernelArg(mKernel, 3, sizeof(unsigned int), &height);
     clSetKernelArg(mKernel, 4, sizeof(unsigned int), &stride);
     clSetKernelArg(mKernel, 5, sizeof(cl_mem),       &mDstBuf[0]);
    
    // Schedule the writing of the inputs
    clEnqueueMigrateMemObjects(mQueue, 2, mSrcBuf, 0, 0, nullptr,  &req->mEvent[0]);
    
    // Schedule the execution of the kernel
    clEnqueueTask(mQueue, mKernel, 1,  &req->mEvent[0], &req->mEvent[1]);
    

    これら 3 つの clEnqueueTask コマンドは、1 つの順序どおりのコマンド キューを使用してキューに追加されます (73 行目)。この結果、すべてのコマンドがキューに追加された順序で実行されます。

    Filter2DDispatcher(
            cl_device_id     &Device,
            cl_context       &Context,
            cl_program       &Program )
      {
            mKernel  = clCreateKernel(Program, "Filter2DKernel", &mErr);
            mQueue   = clCreateCommandQueue(Context, Device, CL_QUEUE_PROFILING_ENABLE, &mErr);
            mContext = Context;
            mCounter = 0;
      }
    

    エミュレーション結果

    生成されたタイムライン トレース レポート (opencl_trace.csv) を確認します。

    vitis_analyzer xrt.run_summary

    注記: run ディレクトリには、xrt.ini というファイルが含まれます。このファイルには、プロファイル サマリ レポートおよびタイムライン トレースなどの追加レポートを生成するランタイム オプションが含まれています。

    Vitis アナライザーが開いたら、左パネルの [Timeline Trace] をクリックします。アプリケーション タイムライン レポートは、ホストとデバイスのイベント情報を収集し、共通のタイムラインに表示します。これは、システムの全体的な状態とパフォーマンスを視覚的に表示して理解するのに役立ちます。

    • タイムラインの最下部に、ホストからキューに追加された各カーネルに 1 本ずつ、合計 3 本の青いバーがあります。1 つの順序どおりのコマンド キューが使用されているので、ホストはカーネル実行を順にキューに追加します。

    • 青いバーの下に、各カーネル実行に 1 本ずつ、合計 3 本の緑色のバーがあります。これらは、FPGA で順に実行されます。 Serial kernel enqueue

    カーネルを同時にエンキューするためのホスト コードの改善

    1. src/host/host.cpp ホスト ファイルの 73 行目を変更します。この行を変更してコマンド キューを順不同コマンド キューとして宣言します。

      コード変更前:

      mQueue   = clCreateCommandQueue(Context, Device, CL_QUEUE_PROFILING_ENABLE, &mErr);
      

      コード変更後:

      mQueue   = clCreateCommandQueue(Context, Device, CL_QUEUE_PROFILING_ENABLE | CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &mErr);
      
    2. (オプション) 変更したホスト コードでハードウェア エミュレーションを実行します。

      ハードウェア エミュレーションを実行する場合、タイムライン トレースを使用して、順不同コマンド キューを使用することによりカーネルがほぼ同時に実行されるように要求できまることを確認します (青のバーはホストでスケジュールされるカーネル エンキュー要求)。

      ホストはこれらの実行を同時にスケジューリングできますが、FPGA 上には 1 つしか CU がなく、カーネルは順次実行されるので、2 つ目および 3 つ目の実行要求は遅れます。
      Sequential kernels
      次の手順では、FPGA 上の CU の数を増やして、ホスト カーネルを同時に実行できるようにします。

    CU 数の増加

    次に、同じカーネルの CU を 3 つ生成するようにリンク手順を変更して、カーネル xclbin をビルドし直します。

    link.cfg を開いて nk 設定を変更します。

    nk = Filter2DKernel:3

    ハードウェア エミュレーションの実行と変更の確認

    1. xclbin ファイルを生成し直します。make clean を実行して 1 つの CU を含む既存の xclbin を削除してから、make を実行して 3 つのカーネル CU を含む新しい xclbin を作成する必要があります。

      make clean make run TARGET=hw_emu
    2. Vitis アナライザーで新しい xrt.run_summary を表示します。

    アプリケーションで 3 つの CU が使用され、カーネル実行が並列実行されるようになったので、アプリケーションの実行速度が上がりました。missing image

まとめ

カーネル リンク プロセスを変更して、FPGA 上の同じカーネル インスタンスを同時に実行する方法を学びました。


メイン ページに戻る

Copyright© 2020-2022 Xilinx