我是数据自动化系统的新手,目前我正在调查和减少样本,这与我的最终目标相关。
提供的文档描述了如何对内核进行优化,以快速减少跨块的大型数组。宿主函数reduce
在reduction_kernel.cu中使用模板在编译时优化各种内核。
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_idata
的部分和填充d_odata
。更具体地说,它将g_idata
的元素与索引2*blockSize*blockIdx.x
相加到2*blockSize*(blockIdx.x + 1)
(不包括在内),并将结果存储在g_odata[blockIdx.x]
中。(编辑-结尾)
总和是通过缩小块的大小来得到的,直到剩下一个块为止。主机代码用于通过在减少的数组上重复启动内核来跨“级别”同步内核。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[1]
;这是第一个块的部分和所必需的。
我错过了一个细节吗?
发布于 2016-05-21 17:44:25
这一点已在数据自动化系统8.0软件包中得到修正。库达8.0很快就会面世。
https://stackoverflow.com/questions/31115128
复制相似问题