CUDA减少和样本:数据竞赛?

时间:2015-06-29 11:59:22

标签: c++ cuda

我是CUDA的新手,目前我正在调查总和减少样本,这与我的最终目标相关。

提供的文档描述了如何优化内核以快速减少跨块的大型数组。 redu_kernel.cu中的主机函数reduce使用模板在编译时优化各种内核。

template <class T>
void reduce(int size, int threads, int blocks,
            int whichKernel, T *d_idata, T *d_odata)
{
    // 
    // Long list with switch statement to have all optimized functions at compile-time
    //

    // amongst which (for instance):
    case 32:
        reduce5<T,  32><<< dimGrid, dimBlock, smemSize >>>(d_idata, d_odata, size);
        break;

编辑:内核reduce5使用部分总和d_odata填充d_idata。更具体地说,它将g_idata与索引2*blockSize*blockIdx.x的元素相加到2*blockSize*(blockIdx.x + 1)(不包括在内),并将结果存储在g_odata[blockIdx.x]中。 (EDIT-END)

通过减少块直到剩下一个块来获得总和。主机代码用于通过在简化阵列上重复启动内核来跨“级别”同步内核。 reduction.cpp中相关的代码位:

template <class T>
T benchmarkReduce(int n, numThreads, numBlocks, /* more args */, 
                  T *h_odata, T *d_idata, T *d_odata) {

    // first kernel launch
    reduce<T>(n, numThreads, numBlocks, whichKernel, d_idata, d_odata);

    // repeated kernel launches
    int s=numBlocks;
    int kernel = whichKernel;

    while (s > cpuFinalThreshold)
    {   
        int threads = 0, blocks = 0;
        getNumBlocksAndThreads(kernel, s, maxBlocks, maxThreads, blocks, threads);

        reduce<T>(s, threads, blocks, kernel, d_odata, d_odata);

        if (kernel < 3) 
            s = (s + threads - 1) / threads;
        else
            s = (s + (threads*2-1)) / (threads*2);  
    }
}

我对第一个内核调用感到满意,该调用将d_idata的部分和存储在d_odata中。我担心第二次内核启动(在while循环中):即内核将读取和写入d_odata ,这可能导致数据赛车。 例如,第二个块可以在第一个块读取其原始值之前将其部分和写入d_odata[1];这是第一个块的部分和所必需的。

我错过了一个细节吗?

1 个答案:

答案 0 :(得分:0)

这已在CUDA 8.0软件包中修复。 CUDA 8.0应该很快就会推出。

相关问题