カーネル ポートのメモリへのマップ - 2023.2 日本語

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

Document ID
UG1393
Release Date
2023-12-13
Version
2023.2 日本語

リンク段階では、カーネルのメモリ ポートが DDR、HBM、および PLRAM を含むメモリ リソースに接続されます。デフォルトでは、v++ リンク プロセスで xclbin ファイルが生成されるときに、すべてのカーネル メモリ インターフェイスが同じグローバル メモリ バンク (または gmem) に接続されます。そのため、メモリ バンクとデータを転送できるのは一度に 1 つのメモリ インターフェイスのみなので、カーネルのパフォーマンスはメモリ アクセスにより制限されます。

Vitis コンパイラでは CU がグローバル メモリ リソースに自動的に接続できますが、各カーネル引数 (またはインターフェイス) が接続されているグローバル メモリ バンクを手動で指定することもできます。帯域幅を最大にし、データ転送を最適化して、全体的なパフォーマンスを改善するには、カーネルとメモリを正しく接続することが重要です。デバイスに演算ユニットが 1 つしかない場合でも、入力と出力引数を別々のグローバル メモリ バンクに割り当てると、入力データと出力データに同時にアクセスできるようになるので、パフォーマンスを向上できます。

次の図に、GitHub の Vitis Examples からの Global Memory Two Banks 例を示します。この例では、カーネルの入力ポインター インターフェイスを DDR バンク 0 に、出力ポインター インターフェイスを DDR バンク 1 に接続しています。

図 1. グローバル メモリの 2 つのバンクの例
重要: 最大 15 までのカーネル インターフェイスを 1 つのグローバル メモリ バンクに接続できます。このため、メモリ インターフェイスが 16 個以上ある場合は、ここで説明するように、--conectivity.sp を使用して接続を複数のメモリ バンクに分散する必要があります。

まず、カーネル引数を別々のバンドルに割り当てて使用可能なインターフェイス ポートを増やし、その引数を別々のメモリ バンクに割り当てます。次の例では、ハードウェア インターフェイス で説明するインターフェイスを使用します。

  1. C/C++ カーネル コードの場合、コンパイル前に INTERFACE プラグマを使って引数を別々のバンドルに割り当てます。
    void cnn( int *pixel, // Input pixel
      int *weights, // Input Weight Matrix
      int *out, // Output pixel
      ... // Other input or Output ports
    		   
    #pragma HLS INTERFACE m_axi port=pixel offset=slave bundle=gmem
    #pragma HLS INTERFACE m_axi port=weights offset=slave bundle=gmem1
    #pragma HLS INTERFACE m_axi port=out offset=slave bundle=gmem
    

    上記の例では、メモリ インターフェイス入力 pixelweights に異なるバンドル名が割り当てらていますが、outpixel とバンドルされています。これにより、gmemgmem1 の 2 つの別々のインターフェイス ポートが作成されます。

    重要: bundle= で名前を指定する場合は、--connectivity.sp オプションを使用して特定のメモリ バンクに割り当てることができるように、すべて小文字を使用してください。
  2. --connectivity.sp オプションを使用するか、--connectivity オプション で説明されるように、コンフィギュレーション ファイルに含めてください。
    たとえば、上記の cnn カーネルの場合は、コンフィギュレーション ファイルで connectivity.sp オプションを次のように指定します。
    [connectivity]
    #sp=<compute_unit_name>.<argument>:<bank name> 
    sp=cnn_1.pixel:DDR[0]          
    sp=cnn_1.weights:DDR[1]
    sp=cnn_1.out:DDR[0]
    

    説明:

    • <compute_unit_name>: connectivity.nk オプションで定義されている CU のインスタンス名 (複数のカーネル インスタンスの作成 を参照)、または複数の CU が指定されていない場合は <kernel_name>_1
    • <argument>: カーネル引数の名前。C/C ++ カーネルの場合、m_axi_ および bundle 名など、HLS INTERFACE プラグマで定義されるカーネル インターフェイス名を指定することもできます。上記の cnn カーネルの場合、ポートは m_axi_gmem および m_axi_gmem1 です。
      ヒント: RTL カーネルの場合、インターフェイスは kernel.xml ファイルで定義されるインターフェイス名で指定されます。
    • <bank_name>: バンク名。4 つの DDR バンクを含むプラットフォームの場合は DDR[0]DDR[1]DDR[2]、および DDR[3] となります。また、メモリを DDR[0:2] などの連続するバンク範囲として指定することもできます。この場合、実行時に XRT によってメモリ バンクが割り当てられます。

      PLRAM、HBM、HP または MIG メモリをサポートするプラットフォームもあり、その場合は PLRAM[0]、HBM[0]、HP[0] または MIG[0] を使用します。プラットフォームで使用可能なグローバル メモリ バンクに関する情報を取得するには、platforminfo を使用します。詳細は、platforminfo ユーティリティ を参照してください。

      DDR メモリ バンクと HBM メモリ バンクの両方を含むプラットフォームでは、別々の AXI インターフェイスを使用して、カーネルが異なるメモリにアクセスできるようにする必要があります。DDR および PLRAM アクセスは、1 つのポートから共有できます。

      ヒント: カーネル インターフェイスを特定のメモリ バンクに割り当てるには、カーネルを配置する SLR を指定する必要があることもあります。詳細は、Alveo アクセラレータ カードでの演算ユニットの SLR への割り当て を参照してください。

Vitis アナライザーで Device Hardware Transaction ビューを使用すると、実際の DDR バンクの通信を確認して DDR の使用を解析できます。

図 2. [Device Hardware Transaction] ビューの DDR バンクのトランザクション