CUDA と OpenCL のプログラミング ガイドを読んでいますが、バンク コンフリクトとは何かがわかりません。彼らは、主題自体について詳しく説明することなく、問題を解決する方法に飛び込むだけです. 誰でもそれを理解するのを手伝ってもらえますか? ヘルプが CUDA/OpenCL のコンテキストにあるのか、それともコンピュータ サイエンス全般のバンク コンフリクトに関連するものなのか、好みはありません。
5 に答える
nvidia (さらに言えば amd) gpu の場合、ローカル メモリは複数のメモリ バンクに分割されます。各バンクは一度に 1 つのデータセットしかアドレス指定できないため、ハーフワープが同じバンクとの間でデータをロード/ストアしようとすると、アクセスをシリアル化する必要があります (これはバンク競合です)。gt200 gpus の場合、16 のバンク (fermi の場合は 32banks)、AMD gpus の場合は 16 または 32 のバンク (57xx 以上: 32、それ以下のすべて: 16)) があり、32 ビットの粒度でインターリーブされます (したがって、バイト 0-3 はバンク 1、バンク 2 の 4-7、...、バンク 1 の 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 ビット値にアクセスする場合、バンクの競合は発生しません。このルールの例外 (すべてのスレッドが独自のバンクにアクセスする必要があります) はブロードキャストです。すべてのスレッドが同じアドレスにアクセスする場合、値は一度だけ読み取られ、すべてのスレッドにブロードキャストされます (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
このような問題は、通常、配列をバッファリングするか、配列内の素数の要素を使用することにより、コンパイラによって回避されます。
http://en.wikipedia.org/wiki/Memory_bank
および
http://mprc.pku.cn/mentors/training/ISCAreading/1989/p380-weiss/p380-weiss.pdf
このページから、メモリバンクの詳細を確認できます。しかし、それは@Grizzlyが言っていることとは少し異なります。このページでは、銀行はこのようなものです
銀行123
アドレス|0、3、6 ... | | 1、4、7 ... | | 2、5、8 ... |
これが役立つことを願っています