【发布时间】:2012-05-04 08:52:50
【问题描述】:
查看 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 的值并将其写入输出?
到目前为止,我尝试了两种方法:(由 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
有什么建议吗?提前致谢 !
【问题讨论】:
-
您能否提供一些
ntr、posidr和pos的典型值?另外,一个典型的计算会产生多少个输出点(CPU 代码中的xcount)? -
@talonmies:我尝试了以下值:ntr = 128、pos = 1 和 posdir = 32。
-
@talonmies:memcpyfrom 符号是正确的方法吗??
-
是的。希望你有一个
cudaMemcpyToSymbol调用为零gcount如果你以原子方式访问它。 -
如何将
cudaMemcpySymbol归零gcount??我知道你可以在内核启动之前显式设置gcount = 0?
标签: c cuda shared-memory