查看 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)将in2的32个值存储在共享内存变量t1中,
(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 内核将焦点切换到 block(0,0,0) 和 thread(32,0,0) 后,out1[0] 的值再次被重写。如何获取/存储每个线程的 out1 的值并将其写入输出?
到目前为止,我尝试了两种方法:(@paseolatis 在 NVIDIA 论坛上建议)
(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
有什么建议么?提前致谢 !