この次の CUDA-C の部分並列和アルゴリズムの実装を理解するのを手伝ってもらえますか? partialSum
共有配列の初期フィルアップを理解するのに問題があります[3 行目から 8 行目]。私は今それを何時間も追跡しましたが、次のコードで開始する必要がある理由がわかりませ2*blockIdx.x*blockDim.x;
んblockIdx.x*blockDim.x;
。
ホスト コード:
numOutputElements = numInputElements / (BLOCK_SIZE<<1);
if (numInputElements % (BLOCK_SIZE<<1)) {
numOutputElements++;
}
#define BLOCK_SIZE 512
dim3 dimGrid(numOutputElements, 1, 1);
dim3 dimBlock(BLOCK_SIZE, 1, 1);
total<<<dimGrid, dimBlock>>>(deviceInput, deviceOutput, numInputElements);
カーネルコード:
1 __global__ void total(float * input, float * output, int len) {
2
3 __shared__ float partialSum[2*BLOCK_SIZE];
4
5 unsigned int t = threadIdx.x;
6 unsigned int start = 2*blockIdx.x*blockDim.x;
7 partialSum[t] = input[start + t];
8 partialSum[blockDim.x + t] = input[start + blockDim.x + t];
9
10 for (unsigned int stride = blockDim.x; stride >=1; stride >>=1)
11 {
12 __syncthreads();
13
14 if (t < stride)
15 partialSum[t] += partialSum[t + stride];
16 }
17 output[blockIdx.x] = partialSum[0];
18 }
合計する要素が 10 個あり、ブロックサイズを 4、ブロックあたり 4 スレッドにすることを選択したとします。したがって、3 つのブロックが使用されますよね? 【ワープのサイズなどは一旦忘れましょう】
blockIdx.x が 2 (2 つの要素を持つ最後のブロック) の場合、開始は (2*2*4=)16 になり、10 より大きく、input
長さを超えます (したがって、partialSum[t]
との両方partialSum[blockDim.x + t]
が変更されず、block2
の共有メモリは空のままです。) もしそうなら、配列の最後の 2 つの要素が失われます!!
blockIdx.x、blockDim.x を間違った方法で取得していると思われます。誰かが私を修正してもらえますか? お願いします!