我正在尝试理解CUDA编程模型及其功能。作为练习,我试图通过函数调用将以下循环结构转换为高效的CUDA内核
//function call
bool gmul(int rowsize,int *Ai,int *Bj,int colsize)
{
for(int i = 0;i < rowsize;i++)
{
for(int j = 0;j < colsize;j++)
{
if(Ai[i] == Bj[j])
{
return true;
}
}
}
return false;
}
//Some for loop in main function is as follows
for(i = 0;i < q ;i++)
{
cbeg = Bjc[i];
cend = Bjc[i+1];
for(j = 0;j < m;j++)
{
beg = Aptr[j];
end = Aptr[j+1];
if(gmul(end - beg,Acol + beg,Bir + cbeg,cend - cbeg))
{
temp++;
}
}
Cjc1[i+1] = temp ;
}
我的函数调用内核如下。
__device__ bool mult(int colsize,int rowsize,int *Aj,int *Bi,int *val)
{
for(int j = 0; j < rowsize;j++)
{
for(int k = 0;k < colsize;k++)
{
if(Aj[j] == Bi[k])
{
return true;
}
}
}
return false;
}
__global__ void kernel(int *Aptr,int *Aj,int *Bptr,int *Bi,int rows,int cols,int *count,int *Cjc)
{
int tid = threadIdx.x + blockIdx.x * blockDim.x;
int i;
if(tid < cols)
{
int beg = Bptr[tid];
int end = Bptr[tid+1];
for(i = 0;i < rows;i++)
{
int cbeg = Aptr[i];
int cend = Aptr[i+1];
if(mult(end - beg,cend - cbeg,Aj+cbeg,Bi+beg,count))
{
//atomicAdd(count,1);
//Changes made are in next line
atomicAdd(Cjc+tid+1,1);
}
}
//atomicAdd(Cjc+tid+1,*count);
}
}
我想要的是每当__device__ mult
返回true
值时,我的全局内核函数应该递增该特定线程的计数器,并且一旦for循环(在内核函数中)结束,它应该将值存储到Cjc
数组中,并将count移交给其他线程以进行递增操作。但是,我没有得到预期的价值。所有线程完成执行后,我在Cjc
数组中得到的所有内容都是最终计数。
我正在使用带有CC 2.0的GTX 480
关于为什么我对此CUDA内核得到错误答案或优化的任何建议/提示将不胜感激。 提前致谢。 的 * ** * **** 解决的 * ** * ** * ****
现在,我面临的一个问题是,每当我达到4000以上时,我就会将数组中所有元素的值都设为0
。以下是我启动内核的方法。
int numBlocks,numThreads;
if(q % 32 == 0)
{
numBlocks = q/32;
numThreads = 32;
}
else
{
numBlocks = (q+31)/32;
numThreads = 32;
}
findkernel<<<numBlocks,numThreads>>>(devAptr,devAcol,devBjc,devBir,m,q,d_Cjc);
我想知道我正在越过块或网格尺寸的任何限制但是对于CC 2.0,我认为我发布足够的块和线程是不对的。我想知道为什么所有的答案都是0
。
答案 0 :(得分:1)
您编写了并行线程,无需同步即可读写count
。线程以不可预测的顺序并发运行,因此线程以不可预测的顺序原子地修改count
和读取count
。表达式*count
将根据确切的执行顺序产生不同的结果。
一旦for循环(在内核函数中)结束,它应该将值存储到
Cjc
数组中,并将count移交给其他线程以进行递增操作。
没有同步,因此没有线程等待另一个线程完成循环。而不是让所有线程共享count
的相同存储,为什么不给每个线程一个不同的存储空间?然后线程不会影响彼此的结果。您可以在此之后运行扫描内核以组合结果。