私はいつもリニア共有メモリ(ロード、ストア、アクセスネイバー)を使っていましたが、バンクコンフリクトを調べるために2Dで簡単なテストを行いました。2D共有メモリをCUDAに配置する方法
次のコードは、1次元グローバルメモリアレイから共有メモリにデータを読み込み、共有メモリからグローバルメモリにコピーバックします。
__global__ void update(int* gIn, int* gOut, int w) {
// shared memory space
__shared__ int shData[16][16];
// map from threadIdx/BlockIdx to data position
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
// calculate the global id into the one dimensional array
int gid = x + y * w;
// load shared memory
shData[threadIdx.x][threadIdx.y] = gIn[gid];
// synchronize threads not really needed but keep it for convenience
__syncthreads();
// write data back to global memory
gOut[gid] = shData[threadIdx.x][threadIdx.y];
}
ビジュアルプロファイラは、共有メモリで競合を報告しました。次のコードは競合を回避します(相違点のみを表示します)
// load shared memory
shData[threadIdx.y][threadIdx.x] = gIn[gid];
// write data back to global memory
gOut[gid] = shData[threadIdx.y][threadIdx.x];
この動作は、超並列プロセッサのプログラミングでは私を混乱させます。我々が読むことができるハンズオンアプローチ:CとCUDAの行列要素は、行の主要な規則に従って線形にアドレス指定された位置に配置されます:
すなわち、行列の行0の要素は、最初に連続する位置に順番に配置される。
これは共有メモリアセンブリに関連していますか?またはスレッドインデックスを使用していますか?多分私は何かを逃していますか?
カーネルの構成は以下の通りです:事前に
// kernel configuration
dim3 dimBlock = dim3 (16, 16, 1);
dim3 dimGrid = dim3 (64, 64);
// Launching a grid of 64x64 blocks with 16x16 threads -> 1048576 threads
update<<<dimGrid, dimBlock>>>(d_input, d_output, 1024);
感謝。
使用しているブロックの寸法を追加できますか?私はそれが(16,16,1)と推測していますが、答える前に確認しておくと良いです。 – talonmies
@talonmies私は、カーネル設定/ launchを質問に追加しました。あなたがコメントしたように、私は(16,16、1)ブロックを使用しています – pQB