説明
OpenCL プログラマのほかの計算デバイスと比較した場合の FPGA の利点は、システム全体のメモリ アーキテクチャをカスタマイズし、計算ユニットに挿入できることです。デフォルトでは、Vitis コンパイラにより、カーネル コードのスタティック コード解析に基づいてローカルおよびプライベート メモリの帯域幅を最大限にする計算ユニット内にメモリ アーキテクチャが生成されます。これらのメモリはカーネル ソース コードの属性に基づいてさらに最適化することが可能であり、ローカルおよびプライベート メモリの物理的なレイアウトおよびインプリメンテーションを指定するのに使用できます。計算ユニットのメモリの物理的なレイアウトを制御する Vitis コンパイラの属性は array_partition
です。
1 次元配列の場合、XCL_ARRAY_PARTITION 属性により、カーネル コード内で宣言された配列が 1 つの物理メモリではなく複数の物理メモリにインプリメントされます。どの分割方法を使用するかは、アプリケーションおよびパフォーマンス要件によって異なります。Vitis コンパイラで使用可能な配列の分割方法は、cyclic
、block
、および complete
です。
構文
この属性は、配列変数の定義と一緒に指定します。
__attribute__((xcl_array_partition(<type>, <factor>,
<dimension>)))
説明:
-
<type>
: 次のいずれかの分割タイプを指定します。-
cyclic
: サイクリック分割では、配列が計算ユニットのロジックにより同時にアクセス可能な複数の小型の物理メモリとしてインプリメントされます。各メモリに要素が 1 つずつ配置され、すべての配列に配置されたら最初の配列に戻って、配列が完全に分割されるまでそれが繰り返されます。 -
block
: ブロック分割では、配列が計算ユニットのロジックにより同時にアクセス可能な複数の小型メモリとしてインプリメントされます。メモリ ブロックに配列からの要素がフルになるまで配置され、次のメモリ ブロックに移動してそれが繰り返されます。 -
complete
: 完全分割では、配列を個々の要素に分割します。1 次元配列の場合は、メモリが個々のレジスタに分割されます。デフォルトの<type>
はcomplete
です。
-
-
<factor>
: サイクリック分割では、<factor>
でカーネル コードの元の配列をいくつの物理メモリに分割するかを指定します。ブロック分割では、<factor>
で元の配列から各物理メモリに配置する要素の数を指定します。重要: 完全分割 (complete
) では<factor>
は指定しません。 -
<dimension>
: 分割する次元を指定します。1 ~ <N> の整数を指定します。Vitis コア開発キットでは、N 次元の配列がサポートされ、配列をどの 1 つの次元でも分割できます。
例 1
次のような配列宣言があるとします。
int buffer[16];
buffer という名前の整数配列には、32 ビット幅の値が 16 個格納されています。この配列に、次の宣言を使用してサイクリック分割を適用します。
int buffer[16] __attribute__((xcl_array_partition(cyclic,4,1)));
この例では、<partition_type>
を cyclic に指定しているので、Vitis で配列の内容が 4 つの物理メモリに分割されます。この属性により、配列 buffer へのアクセスに使用可能なメモリ帯域幅が 4 倍になります。
Vitis コア開発キットでは、計算ユニット内すべての配列で最高 2 つの同時アクセスを保持できます。コードの元の配列を 4 つの物理メモリに分割することにより、計算ユニットで配列 buffer に対する最高 8 つの同時アクセスを保持できます。
例 2
例 1 と同じ整数配列に、次の宣言を使用してブロック分割を適用します。
int buffer[16] __attribute__((xcl_array_partition(block,4,1)));
ブロックのサイズは 4 なので、Vitis コンパイラで 4 つの物理メモリが生成され、各メモリに配列からのデータが順に配置されます。
例 3
例 1 と同じ整数配列に、次の宣言を使用して完全分割を適用します。
int buffer[16] __attribute__((xcl_array_partition(complete, 1)));
この例では、配列がカーネルのプログラマブル ロジックの分散 RAM または 16 個のレジスタに完全に分割されます。完全分割がデフォルトなので、次の宣言を使用しても同じ結果が得られます。
int buffer[16] __attribute__((xcl_array_partition));
これによりメモリ帯域幅が最大のインプリメンテーションが作成されますが、すべてのアプリケーションに適しているわけではありません。カーネル コードによる定数またはデータ依存インデックスを介したデータへのアクセス方法によって、元のコードと同等の機能を確実にするために Vitis コンパイラで各レジスタの周辺に構築する必要のあるサポート ロジックの量が異なります。Vitis コア開発キットでの一般的なベスト プラクティス ガイドラインとして、完全分割は、少なくとも 1 つの次元が定数インデックスを介してアクセスされる配列に適しています。