配列の分割 - 2023.2 日本語

Vitis 高位合成ユーザー ガイド (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 日本語

配列は、ブロックまたは個々の要素に分割できます。Vitis HLS で配列が個々の要素に分割されることもあります。これは、自動分割のコンフィギュレーション設定を使用すると指定できます。配列が複数のブロックに分割されると、1 つの配列は複数の RTL RAM ブロックとしてインプリメントされます。個々の要素に分割される場合、各要素は RTL でレジスタとしてインプリメントされます。どちらの場合も、分割によりさらに多くの要素に並列アクセスできるようになり、パフォーマンスが向上します。デザインのトレードオフは、パフォーマンスとそれを達成するために必要な RAM またはレジスタの数です。

関数をパイプライン処理すると、次のようなエラー メッセージが表示されることがあります。

INFO: [SCHED 204-61] Pipelining loop 'SUM_LOOP'.
WARNING: [SCHED 204-69] Unable to schedule 'load' operation ('mem_load_2', 
bottleneck.c:62) on array 'mem' due to limited memory ports.
WARNING: [SCHED 204-69] The resource limit of core:RAM:mem:p0 is 1, current 
assignments: 
WARNING: [SCHED 204-69]     'load' operation ('mem_load', bottleneck.c:62) on array 
'mem',
WARNING: [SCHED 204-69] The resource limit of core:RAM:mem:p1 is 1, current 
assignments: 
WARNING: [SCHED 204-69]     'load' operation ('mem_load_1', bottleneck.c:62) on array 
'mem',
INFO: [SCHED 204-61] Pipelining result: Target II: 1, Final II: 2, Depth: 3.

上記の Vitis HLS のメッセージは、メモリ ポートが限られているため、メモリへの load (読み込み) 操作 (mem_load_2) をスケジューリングできず、指定された開始間隔 (II) 1 を達成できないことを示しています。「The resource limit for core:RAM:mem:p0 is 1」と記述されているように core:RAM:mem:p0 のリソース制限は 1 で、62 行目の mem_load 演算で使用されてしまっています。ブロック RAM の 2 つ目のポートにもリソースが 1 つしかなく、これも mem_load_1 演算で使用されています。Vitis HLS は、このメモリ ポートの競合により、最終的な II が指定した 1 ではなく 2 になったことをレポートします。

この問題は、通常配列が原因で発生します。最上位関数へのインターフェイスではない配列は、ブロック RAM (最大 2 つのデータ ポート) としてインプリメントされます。これにより、read/write (または load/store) 集中型アルゴリズムのスループットが制限される可能性があります。配列 (1 つのブロック RAM リソース) を複数の小型の配列 (複数のブロック RAM) に分割してポート数を増加することにより、バンド幅を向上できることがあります。

配列を分割するには、ARRAY_PARTITION 指示子を使用します。Vitis HLS には、次の図に示すように 3 つの配列分割方法があります。これらの分割方法は、次のとおりです。

block
元の配列の連続した要素が同じサイズのに分割されます。
cyclic
元の配列の要素がインターリーブされて同じサイズのブロックに分割されます。
complete
デフォルトでは配列が個別エレメントに分割されます。これは、メモリの複数のレジスタへの分解に相当します。
図 1. 配列の分割

block および cyclic 分割では、factor オプションを使用して作成する配列の数を指定します。前の図では、factor オプション 2 が使用され、配列が 2 つの配列に分割されています。配列の要素数がこの係数の整数倍ではない場合、最後の配列に含まれる要素数は少なくなります。

多次元配列を分割する際は、dimension オプションを使用して、分割する次元を指定できます。次の図に、次のコード例を異なる dimension オプションを使用して分割した場合を示します。

void foo (...) {
 int  my_array[10][6][4];
   ...   
}

dimension を 3 に設定すると 4 つの配列に、dimension を 1 に設定すると 10 個の配列に分割されます。dimension を 0 に設定すると、すべての次元が分割されます。

図 2. 多次元配列の分割