回答:
nvidia(およびその問題のamd)gpusの場合、ローカルメモリはメモリバンクに分割されます。各バンクは一度に1つのデータセットしかアドレス指定できないため、ハーフワープが同じバンクとの間でデータをロード/ストアしようとすると、アクセスをシリアル化する必要があります(これはバンクの競合です)。gt200 gpusの場合、16バンク(fermiの場合は32バンク)、AMD gpusの場合は16または32バンク(57xx以上:32、以下はすべて16))であり、32ビットの粒度でインターリーブされています(バイト0-3はバンク1のバンク1、4〜7、バンク2、...、64〜69など)。より良い視覚化のために、それは基本的に次のようになります:
Bank | 1 | 2 | 3 |...
Address | 0 1 2 3 | 4 5 6 7 | 8 9 10 11 |...
Address | 64 65 66 67 | 68 69 70 71 | 72 73 74 75 |...
...
したがって、ハーフワープの各スレッドが連続する32ビット値にアクセスする場合、バンクの競合はありません。このルールの例外(すべてのスレッドは独自のバンクにアクセスする必要があります)はブロードキャストです。すべてのスレッドが同じアドレスにアクセスする場合、値は1回だけ読み取られ、すべてのスレッドにブロードキャストされます(GT200の場合、ハーフワープにアクセスするすべてのスレッドである必要があります。同じアドレス、iirc fermiおよびAMD gpusは、同じ値にアクセスする任意の数のスレッドに対してこれを実行できます)。
並行してアクセスできる共有メモリは、モジュール(バンクとも呼ばれます)に分割されます。同じバンクで2つのメモリロケーション(アドレス)が発生すると、バンクの競合が発生し、その間にアクセスがシリアルで行われるため、パラレルアクセスの利点が失われます。
簡単に言うと、バンク競合は、メモリアクセスパターンがメモリシステムで使用可能なバンク間でIOを分散できない場合です。次の例は、その概念を詳しく説明しています。
2次元の512x512整数配列があり、DRAMまたはメモリシステムには512バンクがあるとします。デフォルトでは、配列データは、arr [0] [0]がバンク0に、arr [0] [1]がバンク1に、arr [0] [2]がバンク2に行くようにレイアウトされます。 arr [0] [511]はバンク511に移動します。arr[x] [y]を一般化するには、バンク番号yを使用します。これで、いくつかのコード(以下に示す)が列メジャー方式でデータにアクセスし始めます。yを一定に保ちながらxを変更すると、最終的な結果として、連続するすべてのメモリアクセスが同じバンクにヒットするため、バンクの競合が発生します。
int arr[512][512];
for ( j = 0; j < 512; j++ ) // outer loop
for ( i = 0; i < 512; i++ ) // inner loop
arr[i][j] = 2 * arr[i][j]; // column major processing
このような問題は、通常、配列をバッファリングするか、配列内の素数の要素を使用することにより、コンパイラによって回避されます。
(CUDA Bank Conflict)これがお役に立てば幸いです。これは非常に良い説明です...
http://en.wikipedia.org/wiki/Memory_bank
および
http://mprc.pku.cn/mentors/training/ISCAreading/1989/p380-weiss/p380-weiss.pdf
このページから、メモリバンクに関する詳細を見つけることができます。しかし、@ Grizzlyが言うこととは少し異なります。このページでは銀行はこんな感じ
銀行1 2 3
アドレス| 0、3、6 ... | | 1、4、7 ... | | 2、5、8 ... |
これが役に立てば幸い