NVIDIA CUDA ウェビナー ページのこのウェビナーに興味があるかもしれません。バンクを含む共有メモリは、このウェビナーの スライド 35 ~ 45 でも説明されています。
一般に、共有メモリ バンクの競合は、2 つの異なるスレッドが (同じカーネル命令から) 下位 4 ビット (cc2.0 以前のデバイス) または 5 ビット (cc2.0 以降のデバイス) の共有メモリ内の場所にアクセスしようとすると発生する可能性があります。アドレスのデバイス) は同じです。バンク競合が発生すると、共有メモリ システムは同じバンク内のロケーションへのアクセスをシリアル化するため、パフォーマンスが低下します。パディングは、一部のアクセス パターンでこれを回避しようとします。cc2.0 以降では、すべてのビットが同じ (つまり、同じ位置) の場合、バンク競合は発生しないことに注意してください。
絵的には、次のように見ることができます。
__shared__ int A[2048];
int my;
my = A[0]; // A[0] is in bank 0
my = A[1]; // A[1] is in bank 1
my = A[2]; // A[2] is in bank 2
...
my = A[31]; // A[31] is in bank 31 (cc2.0 or newer device)
my = A[32]; // A[32] is in bank 0
my = A[33]; // A[33] is in bank 1
現在、ワープ内のスレッド間で共有メモリにアクセスすると、バンクの競合が発生する可能性があります。
my = A[threadIdx.x]; // no bank conflicts or serialization - handled in one trans.
my = A[threadIdx.x*2]; // 2-way bank conflicts - will cause 2 level serialization
my = A[threadIdx.x*32]; // 32-way bank conflicts - will cause 32 level serialization
上記の 2 方向のバンク コンフリクトを詳しく見てみましょう。2を乗算threadIdx.x
しているため、スレッド 0 はバンク 0 のロケーション 0 にアクセスしますが、スレッド 16 はバンク 0 にあるロケーション 32 にアクセスし、バンク競合が発生します。上記の 32 ウェイの例では、すべてのアドレスがバンク 0 に対応します。したがって、共有メモリへの 32 のトランザクションは、すべてシリアル化されるため、この要求を満たすために発生する必要があります。
質問に答えるために、たとえば、アクセスパターンが次のようになることがわかっているとします。
my = A[threadIdx.x*32];
次に、データストレージをパディングしてA[32]
、ダミー/パッドの場所にする場合がA[64]
ありますA[96]
。次に、次のように同じデータを取得できます。
my = A[threadIdx.x*33];
そして、銀行の競合なしでデータを取得します。
お役に立てれば。