CUDA:Mark Harris 的并行缩减样本不就是对每个线程块求和吗?
CUDA: Isn't Mark Harris's parallel reduction sample just summing each thread block?
他的幻灯片链接:
http://docs.nvidia.com/cuda/samples/6_Advanced/reduction/doc/reduction.pdf
这是他为第一个版本的并行归约编写的代码:
__global__ void reduce0(int *g_idata, int *g_odata) {
extern __shared__ int sdata[];
// each thread loads one element from global to shared mem
unsigned int tid = threadIdx.x;
unsigned int i = blockIdx.x*blockDim.x + threadIdx.x;
sdata[tid] = g_idata[i];
__syncthreads();
// do reduction in shared mem
for(unsigned int s=1; s < blockDim.x; s *= 2) {
if (tid % (2*s) == 0) {
sdata[tid] += sdata[tid + s];
}
__syncthreads();
}
// write result for this block to global mem
if (tid == 0) g_odata[blockIdx.x] = sdata[0];
}
他后来对其进行了优化。这怎么不只是对每个线程块的所有int求和,并将答案放在另一个向量中?这就是它的本意吗?*g_odata本身不是一个向量吗?因为它将和放在向量中的每个"blockIdx.x"点上?如何将向量g_idata求和为一个数字?
这怎么不只是对每个线程块的所有int求和,并将答案放在另一个向量中?
它正是这样做的。
这就是它的本意吗?
是的。
g_odata
本身不是一个向量吗?因为它把和放在向量中的每个"blockIdx.x"点上?
是的,它是包含块级和的向量。
如何将向量g_idata求和为一个数字?
调用内核两次。在原始数据集上一次,在上一次调用的矢量输出上一次(块级总和)。请注意,第二步只使用一个块,并且要求每个块可以启动足够的线程来覆盖整个向量,即上一步的每个和一个线程。如果您查看旨在伴随您链接的演示的cuda示例代码,您将发现这样的调用序列,例如在reduction.cpp
的第304和333行。对reduce<T>
的第二次调用执行对部分块和求和的归约,如第324行的注释所示:
304:reduce<T>(n, numThreads, numBlocks, whichKernel, d_idata, d_odata);
// check if kernel execution generated an error
getLastCudaError("Kernel execution failed");
if (cpuFinalReduction)
{
// sum partial sums from each block on CPU
// copy result from device to host
checkCudaErrors(cudaMemcpy(h_odata, d_odata, numBlocks*sizeof(T), cudaMemcpyDeviceToHost));
for (int i=0; i<numBlocks; i++)
{
gpu_result += h_odata[i];
}
needReadBack = false;
}
else
{
324: // sum partial block sums on GPU
int s=numBlocks;
int kernel = whichKernel;
while (s > cpuFinalThreshold)
{
int threads = 0, blocks = 0;
getNumBlocksAndThreads(kernel, s, maxBlocks, maxThreads, blocks, threads);
333: reduce<T>(s, threads, blocks, kernel, d_odata, d_odata);
注意来自线304处的第一次缩减的输出CCD_ 4作为输入传递到线333上的第二次缩减。
还要注意,内核分解的必要性和这种方法在您在幻灯片3-5上链接的演示中有介绍。
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 在C++中使用cURL和多线程
- 为什么我的C#代码在调用回C++COM直到Task时会暂停.等待/线程.加入
- 在cuda线程之间共享大量常量数据
- 如何将元素添加到数组的线程安全函数?
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- 异常属于C++中的线程还是进程
- C++中的线程安全删除
- C++使用params创建线程函数会导致转换错误
- 类与私有变量的其他类之间的线程安全性
- CoInitialize()在单独的线程上崩溃而不返回
- c++中的线程池
- 线程之间的布尔停止信号
- 为什么std::async使用同一个线程运行函数
- 循环中的线程 Runnin 用于对 c++ 中的数字求和
- CUDA:Mark Harris 的并行缩减样本不就是对每个线程块求和吗?
- 多线程c++程序加速一个求和循环