2

10 行 96 列の 2D ホスト配列があります。この配列を cuda デバイスのグローバル メモリに線形にロードします。つまり、行 1、行 2、行 3 ... 行 10 です。

配列は float 型です。私のカーネルでは、各スレッドがデバイスのグローバル メモリから 1 つの float 値にアクセスします。

 The BLOCK_SIZE I use is = 96
 The GRID_DIM I use is = 10

合体アクセスの「Cuda Cプログラミングガイド」から理解した今、使用しているパターンは正しく、ワープによってメモリ位置に連続してアクセスします。ただし、メモリ 128 バイトのメモリ アラインメントに関する条項があります。私は理解できません。

Q1) 128 バイトのメモリ アラインメント。ワープ内の各スレッドは、アドレス 0x00 (たとえば) から 0x80 までの 4 バイトにアクセスする必要があるということですか?

Q2) では、シナリオでは非合体アクセスを行うのでしょうか?

私の理解では、0x00 から 0x80 などのアドレス範囲から、1 つのスレッドが 4 バイトで 1 つのメモリ アクセスを行う必要があります。ワープからのスレッドがその外側の場所にアクセスする場合、それは結合されていないアクセスです。

4

1 に答える 1

9

グローバル メモリからのロードは通常、128 バイトの境界に合わせて 128 バイトのチャンクで行われます。合体メモリ アクセスとは、ワープからのすべてのアクセスを 128 バイトの 1 つのチャンクに保持することを意味します。(古いカードでは、メモリはスレッド ID の順にアクセスする必要がありましたが、新しいカードではこの要件がなくなりました。)

ワープ内の 32 のスレッドがそれぞれ float を読み取る場合、グローバル メモリから合計 128 バイトを読み取ることになります。メモリが正しく配置されている場合、すべての読み取りは同じブロックから行われます。アライメントがオフの場合、2 つの読み取りが必要になります。のようなことをするa[32*i]と、各アクセスはグローバル メモリ内の異なる 128 バイト ブロックから発生するため、非常に遅くなります。

ワープ内のすべてのスレッドが同じブロックにアクセスする限り、どのブロックにアクセスしてもかまいません。

96 個の浮動小数点数の配列がある場合i、ワープ内のインデックスを持つ各スレッドが にアクセスa[i]すると、結合された読み取りになります。a[i+32]またはと同じa[i+64]です。

したがって、Q1 に対する答えは、すべてのスレッドが 128 バイト境界に整列された長さ 128 バイトの同じブロック内に留まる必要があるということです。

Q2 に対する答えは、配列が正しく配置されていて、アクセスがスレッド ID とすべてのスレッドで同じ整数をa[32*x+i]持つ形式である場合、アクセスは結合されるということです。ix

プログラミング ガイドのセクション 5.3.2.1.1 によると、メモリは常に少なくとも 256 バイト境界で整列されるため、 で作成された配列cudaMallocは常に正しく整列されます。

于 2013-05-30T23:04:45.050 に答える