Mark Harris のリダクションの例を見て、スレッドにリダクション操作なしで中間値を格納できるかどうかを確認しようとしています。
たとえば、CPU コード:
for(int i = 0; i < ntr; i++)
{
for(int j = 0; j < pos* posdir; j++)
{
val = x[i] * arr[j];
if(val > 0.0)
{
out[xcount] = val*x[i];
xcount += 1;
}
}
}
同等の GPU コード:
const int threads = 64;
num_blocks = ntr/threads;
__global__ void test_g(float *in1, float *in2, float *out1, int *ct, int posdir, int pos)
{
int tid = threadIdx.x + blockIdx.x*blockDim.x;
__shared__ float t1[threads];
__shared__ float t2[threads];
int gcount = 0;
for(int i = 0; i < posdir*pos; i += 32) {
if (threadIdx.x < 32) {
t1[threadIdx.x] = in2[i%posdir];
}
__syncthreads();
for(int i = 0; i < 32; i++)
{
t2[i] = t1[i] * in1[tid];
if(t2[i] > 0){
out1[gcount] = t2[i] * in1[tid];
gcount = gcount + 1;
}
}
}
ct[0] = gcount;
}
ここでやろうとしていることは、次の手順です。
(1)共有メモリ変数t1にin2の値を32個格納し、
(2) i と in1[tid] の各値について、t2[i] を計算し、
(3) if t2[i] > 0
i の特定の組み合わせについてt2[i]*in1[tid]
、out1[gcount]
しかし、私の出力はすべて間違っています。t2[i] が 0 より大きい回数をすべて取得することさえできません。
各 i および tid の gcount の値を保存する方法に関する提案はありますか?? デバッグしていると、ブロック (0,0,0) とスレッド (0,0,0) の t2 の値が更新されていることがわかります。CUDA カーネルがフォーカスをブロック (0,0,0) とスレッド (32,0,0) に切り替えた後、out1[0] の値が再び書き直されます。各スレッドの out1 の値を取得/保存し、それを出力に書き込むにはどうすればよいですか?
これまでに 2 つのアプローチを試しました: (NVIDIA フォーラムで @paseolatis が提案)
(1) 定義済みoffset=tid*32; and replace out1[gcount] with out1[offset+gcount]
、
(2)定義
__device__ int totgcount=0; // this line before main()
atomicAdd(&totgcount,1);
out1[totgcount]=t2[i] * in1[tid];
int *h_xc = (int*) malloc(sizeof(int) * 1);
cudaMemcpyFromSymbol(h_xc, totgcount, sizeof(int)*1, cudaMemcpyDeviceToHost);
printf("GPU: xcount = %d\n", h_xc[0]); // Output looks like this: GPU: xcount = 1928669800
助言がありますか?前もって感謝します !