C++ CUDA优化不起作用
我找到了这个PDF(),它引导您通过几种方法来优化CUDA中的reduce操作,我正试图跟进。对于reduce#5,建议使用以下代码展开循环的最后6次迭代:C++ CUDA优化不起作用,c++,cuda,reduce,C++,Cuda,Reduce,我找到了这个PDF(),它引导您通过几种方法来优化CUDA中的reduce操作,我正试图跟进。对于reduce#5,建议使用以下代码展开循环的最后6次迭代: if (tid < 32) { sdata[tid] += sdata[tid + 32]; sdata[tid] += sdata[tid + 16]; sdata[tid] += sdata[tid + 8]; sdata[tid] += sdata[tid + 4]; sdata[tid] += sdata[
if (tid < 32)
{
sdata[tid] += sdata[tid + 32];
sdata[tid] += sdata[tid + 16];
sdata[tid] += sdata[tid + 8];
sdata[tid] += sdata[tid + 4];
sdata[tid] += sdata[tid + 2];
sdata[tid] += sdata[tid + 1];
}
if(tid<32)
{
sdata[tid]+=sdata[tid+32];
sdata[tid]+=sdata[tid+16];
sdata[tid]+=sdata[tid+8];
sdata[tid]+=sdata[tid+4];
sdata[tid]+=sdata[tid+2];
sdata[tid]+=sdata[tid+1];
}
上一张幻灯片甚至说:
- 随着减少的进行,#“活动”线程减少
- 当s时,您需要使用volatile关键字,正如njuffa在下面评论的那样
这里有同一份文件的更新版本。
这里有一个等效的例子#6供参考
template <unsigned int blockSize> __device__ void warpReduce(volatile int *sdata, unsigned int tid) { if (blockSize >= 64) sdata[tid] += sdata[tid + 32]; if (blockSize >= 32) sdata[tid] += sdata[tid + 16]; if (blockSize >= 16) sdata[tid] += sdata[tid + 8]; if (blockSize >= 8) sdata[tid] += sdata[tid + 4]; if (blockSize >= 4) sdata[tid] += sdata[tid + 2]; if (blockSize >= 2) sdata[tid] += sdata[tid + 1]; } template <unsigned int blockSize> __global__ void reduce6(int *g_idata, int *g_odata, unsigned int n) { extern __shared__ int sdata[]; unsigned int tid = threadIdx.x; unsigned int i = blockIdx.x*(blockSize*2) + tid; unsigned int gridSize = blockSize*2*gridDim.x; sdata[tid] = 0; while (i < n) { sdata[tid] += g_idata[i] + g_idata[i+blockSize]; i += gridSize; } __syncthreads(); if (blockSize >= 512) { if (tid < 256) { sdata[tid] += sdata[tid + 256]; } __syncthreads(); } if (blockSize >= 256) { if (tid < 128) { sdata[tid] += sdata[tid + 128]; } __syncthreads(); } if (blockSize >= 128) { if (tid < 64) { sdata[tid] += sdata[tid + 64]; } __syncthreads(); } if (tid < 32) warpReduce(sdata, tid); if (tid == 0) g_odata[blockIdx.x] = sdata[0]; }
除非模板 __设备\uuuuvoid warpReduce(volatile int*sdata,unsigned int tid){ 如果(块大小>=64)sdata[tid]+=sdata[tid+32]; 如果(块大小>=32)sdata[tid]+=sdata[tid+16]; 如果(块大小>=16)sdata[tid]+=sdata[tid+8]; 如果(块大小>=8)sdata[tid]+=sdata[tid+4]; 如果(块大小>=4)sdata[tid]+=sdata[tid+2]; 如果(块大小>=2)sdata[tid]+=sdata[tid+1]; } 模板 __全局无效归约6(int*g\u-idata,int*g\u-odata,无符号int-n){ 外部共享数据数据[]; unsigned int tid=threadIdx.x; 无符号整数i=blockIdx.x*(blockSize*2)+tid; unsigned int gridSize=blockSize*2*gridDim.x; sdata[tid]=0; 而(i
=512){if(tid<256){sdata[tid]+=sdata[tid+256];} if(blockSize>=256){if(tid<128){sdata[tid]+=sdata[tid+128];} if(blockSize>=128){if(tid<64){sdata[tid]+=sdata[tid+64];} 如果(tid<32)减少(sdata,tid); 如果(tid==0)g_odata[blockIdx.x]=sdata[0]; }
具有sdata
属性,否则此代码不太可能按预期工作。编译器无法检测到的volatile
-块中的语句之间存在隐式数据依赖关系,它很可能会将所有if
读取拉到块的开头,以增加代码的延迟容差。我建议对CUDA使用最新的文档,而不是过时的文档。@Johnathan Olson我也实现了reduce6,并且遇到了相同的问题,除非我在每次写入sdata后调用uu syncthreads()。@njuffa将sdata
添加到sdata似乎已经解决了它!我不知道该文档有多旧,我只是在寻找优化reduce算法的方法时偶然发现了它。@Moohasha该文档似乎来自CUDA 1.1 beta版,所以可能要追溯到2007年底左右。感谢njuffa,编辑了上述内容volatile
- 当s时,您需要使用volatile关键字,正如njuffa在下面评论的那样
这里有同一份文件的更新版本。
这里有一个等效的例子#6供参考