0

私は約10個numpyのアイテムの配列を持っていnます。グローバル ID を持つ OpenCL ワーカーは、各配列iの th 要素のみを調べます。iメモリをどのように配置すればよいですか?

グラフィックス カードの配列をインターリーブすることを考えていましたが、ワークグループのメモリ アクセス パターンを理解していないため、パフォーマンスが向上するかどうかはわかりません。

4

1 に答える 1

1

私はnumpyに慣れていませんが、次の場合:

  • グローバルIDを持つスレッドは要素iを調べiます(あなたが言及したように)
  • データ型のメモリ配置が適切である (4、8、16)
  • 各スレッドは一度に 32、64、128 ビットを読み取ります

合体したメモリアクセスにより、最適なメモリスループットを達成できるはずです。この場合、インターリーブによってパフォーマンスが向上することはありません。

最後の 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 ビットのメモリ転送に結合され、メモリ スループットが最大化されます。

于 2013-09-03T07:15:14.277 に答える