C++ CUDA优化不起作用

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[

我找到了这个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[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
      -块中的语句之间存在隐式数据依赖关系,它很可能会将所有
      sdata
      读取拉到块的开头,以增加代码的延迟容差。我建议对CUDA使用最新的文档,而不是过时的文档。@Johnathan Olson我也实现了reduce6,并且遇到了相同的问题,除非我在每次写入sdata后调用uu syncthreads()。@njuffa将
      volatile
      添加到sdata似乎已经解决了它!我不知道该文档有多旧,我只是在寻找优化reduce算法的方法时偶然发现了它。@Moohasha该文档似乎来自CUDA 1.1 beta版,所以可能要追溯到2007年底左右。感谢njuffa,编辑了上述内容