私は約10個numpy
のアイテムの配列を持っていn
ます。グローバル ID を持つ OpenCL ワーカーは、各配列i
の th 要素のみを調べます。i
メモリをどのように配置すればよいですか?
グラフィックス カードの配列をインターリーブすることを考えていましたが、ワークグループのメモリ アクセス パターンを理解していないため、パフォーマンスが向上するかどうかはわかりません。
私は約10個numpy
のアイテムの配列を持っていn
ます。グローバル ID を持つ OpenCL ワーカーは、各配列i
の th 要素のみを調べます。i
メモリをどのように配置すればよいですか?
グラフィックス カードの配列をインターリーブすることを考えていましたが、ワークグループのメモリ アクセス パターンを理解していないため、パフォーマンスが向上するかどうかはわかりません。
私はnumpyに慣れていませんが、次の場合:
i
を調べi
ます(あなたが言及したように)合体したメモリアクセスにより、最適なメモリスループットを達成できるはずです。この場合、インターリーブによってパフォーマンスが向上することはありません。
最後の 2 つのポイントのいずれかが満たされていない場合、インターリーブによってそれらを達成できる可能性があり、パフォーマンスが向上する可能性があります。
編集:構造体の配列 (SoA) と構造体の配列 (AoS)
この点は、文献によく見られます。私はそれを短くします:
SoA が AoS よりも望ましいのはなぜですか? 32 ビット データ型の配列が 10 個あるとします。AoS ソリューションは次のようになります。
struct Data
{
float a0;
float a1;
...
float a9;
}; // 10 x 32bit = 320 bit
struct Data array[512];
メモリの読み取りはどのようになりますか? メモリーは、メモリー転送を結合できませんでした。ただし、読み取る必要があるコードは非常に短いです。
Data a = array[i];
運が良ければ、コンパイラは、少なくとも読み取り命令の一部をマージするのに十分なほどスマートです。オプションは、明示的なメモリ アラインメントです。これにより、GPU で非常に制限されているグローバル メモリが無駄になります。
今SoAソリューション:
struct Data
{
float a0[512];
float a1[512];
...
float a9[512];
};
struct Data array;
メモリにアクセスする作業はもう少し複雑ですが、すべてのアクセスを合体読み取りに組み合わせることができ、メモリのアライメントは必要ありません。また、構造体を忘れて、各配列をそのまま使用しても、パフォーマンスの問題はありません。
使用できるもう 1 つのことは、ベクトル化されたデータ型です (numpy 配列でこれが許可されている場合)。float2、float4 (または int、double などの他の単純なデータ型) を使用して、結合されたメモリ転送を利用できます。つまり、float4 配列へのすべての読み取りが 128 ビットのメモリ転送に結合され、メモリ スループットが最大化されます。