ローカル メモリ帯域幅の増加

このセクションでは、Vivado HLS で提供されているローカル メモリ帯域幅を増加するいくつかの方法を示します。これらの方法は、ループのパイプライン処理およびループ展開と共に使用してシステム パフォーマンスを向上できます。

C/C++ プログラムでは、配列は理解しやすく便利なコンストラクトです。配列を使用すると、アルゴリズムを簡単にキャプチャして理解できます。Vivado HLS では、各配列はデフォルトでは 1 つのポート メモリ リソースを使用してインプリメントされますが、このようなメモリ インプリメンテーションはパフォーマンス指向のプログラムでは最適なメモリ アーキテクチャでないことがあります。ループのパイプライン処理とループ展開の最後に、制限されたメモリ ポートにより発生するリソース競合の例を示しました。

配列の分割

配列は、より小型の配列に分割できます。メモリの物理的なインプリメンテーションでは、読み出しポートと書き込みポートの数に制限があり、ロード/ストア集約型のアルゴリズムではスループットが制限されます。元の配列 (1 つのメモリ リソースとしてインプリメント) を複数の小型の配列 (複数のメモリとしてインプリメント) に分割してロード/ストア ポートの有効数を増加させることにより、メモリ帯域幅を向上できる場合があります。

Vivado HLS には、次の図のような 3 タイプの配列パーティション方法があります。
  1. block: 元の配列の連続したエレメントが同じサイズのブロックに分割されます。
  2. cyclic: 元の配列のエレメントがインターリーブされて同じサイズのブロックに分割されます。
  3. complete: デフォルトでは配列が個別エレメントに分割されます。これは、配列をメモリとしてではなく複数のレジスタとしてインプリメントすることに対応します。

図: 配列の分割



Vivado HLS で配列をパーティションするには、これをハードウェア関数ソース コードに挿入します。
#pragma HLS array_partition variable=<variable> <block, cyclic, complete> factor=<int> dim=<int>
block および cyclic 分割では、factor オプションを使用して作成する配列の数を指定できます。上記の図では、係数として 2 が使用され、2 つの配列に分割されています。配列に含まれる要素数が指定された係数の整数倍でない場合、最後の配列に含まれる要素数はほかの配列よりも少なくなります。
多次元配列を分割する場合は、dim オプションを使用してどの次元を分割するかを指定できます。次の図に、多次元配列の異なる次元を分割した例を示します。

図: 多次元配列の分割



配列の形状変更

配列の形状を変更して、メモリ帯域幅を増加できます。形状変更では、元の配列の 1 つの次元から異なる要素を取り出して、1 つの幅の広い要素に結合します。配列の形状変更は配列の分割に似ていますが、複数の配列に分割するのではなく、配列の要素の幅を広くします。次の図に、配列の形状変更の概念を示します。

図: 配列の形状変更



Vivado HLS で配列の形状を変更するには、これをハードウェア関数ソース コードに挿入します。
#pragma HLS array_reshape variable=<variable> <block, cyclic, complete> factor=<int> dim=<int>
オプションは、配列分割プラグマと同じです。