0

我正在尝试了解 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数组中并将计数移交给其他线程用于增量操作。但是,我没有得到预期值。我在这个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.

4

1 回答 1

1

count您已经编写了无需同步即可读取和写入的并行线程。线程以不可预知的顺序并发运行,因此线程以不可预知的顺序原子地修改count和读取count。该表达式*count将根据确切的执行顺序产生不同的结果。

一旦 for 循环(在内核函数中)结束,它应该将值存储到Cjc数组中,并将计数移交给其他线程进行增量操作。

没有同步,所以没有线程等待另一个线程完成循环。与其让所有线程共享相同的存储空间count,为什么不给每个线程一个不同的存储空间呢?然后线程将不会影响彼此的结果。您可以在此之后运行扫描内核以组合结果。

于 2012-07-30T04:54:53.797 回答