使用2D块的CUDA点积

使用2D块的CUDA点积,cuda,gpu,gpgpu,nvidia,Cuda,Gpu,Gpgpu,Nvidia,我有以下代码,在一维块中使用时效果很好: __global__ void dot_product_large_arrays( int N, double *a, double *b, double *res) { __shared__ double cache[TILE_DIM]; int tid = threadIdx.x + blockIdx.x * blockDim.x; int i = 0, cacheIndex = 0; do

我有以下代码,在一维块中使用时效果很好:

__global__ void dot_product_large_arrays( int N, double *a, double *b,
                     double *res)
{

  __shared__ double cache[TILE_DIM];
  int tid = threadIdx.x + blockIdx.x * blockDim.x;
  int i = 0, cacheIndex = 0;
  double temp = 0;
  cacheIndex = threadIdx.x;

  while (tid < N) {
    temp += a[tid] * b[tid];
    tid += blockDim.x*gridDim.x;
  }
  cache[cacheIndex] = temp;
  __syncthreads();

  for (i = blockDim.x/2; i > 0; i>>=1) {
    if (threadIdx.x < i) {
      cache[threadIdx.x] += cache[threadIdx.x + i];
    }
    __syncthreads();
  }
  __syncthreads();

  if (cacheIndex == 0) {
    atomicAdd(res, cache[0]);
  }
}
还有我的内核调用

int totalThreads = 9000*9000;
int blockSize = 512;
int blockDimY = 256;
int blockDimX = (totalThreads/( blockSize*blockDimY))+ 1;

dim3 dimGrid(blockDimX,blockDimY);
dim3 dimBlock(blockSize);

dot_product_large_arrays <<< dimGrid, dimBlock >>>(totalThreads, d_a, d_b, d_res);
inttotalthreads=9000*9000;
int blockSize=512;
int blockDimY=256;
int blockDimX=(totalThreads/(blockSize*blockDimY))+1;
dim3 dimGrid(块DIMX、块DIMY);
dim3 dimBlock(块大小);
dot_product_large_array>(总线程、d_a、d_b、d_res);

它可以编译,可以运行,但永远不会完成(?),你知道我这里做错了什么吗?

下面的行将增加tid似乎就是问题所在:

 while (tid < N) {  
    temp += a[tid] * b[tid];  
    tid += blockDim.x * gridDim.x * blockIdx.y * grimDim.y; //blockIdx.y can be zero
 }
while(tid

至少有一个块的块y索引为0,这意味着您将增加0,并导致一个或多个线程进入无限循环

下面增加tid的那一行似乎就是问题所在:

 while (tid < N) {  
    temp += a[tid] * b[tid];  
    tid += blockDim.x * gridDim.x * blockIdx.y * grimDim.y; //blockIdx.y can be zero
 }
while(tid

至少有一个块的块y索引为0,这意味着您将增加0,并导致一个或多个线程进入无限循环

对于9000*9000输入阵列,运行此内核完全不需要运行9000*9000线程。也不需要修改它来使用2D网格。@Talonmes,请你进一步解释一下好吗?这听起来很有趣,带有网格步长的while循环旨在能够累积任意长度的输入数组的部分和。这就是把循环放在首位的全部意义…@Talonmes我已经照你说的做了。谢谢。现在没事了。但是我注意到,当使用192个线程和
min(8*148999*8999)
块时,正确性并不好,但如果使用128个线程和
min(8*148999*8999)
块,则正确性是完美的。你对此有什么解释吗?根据CUDA占用率计算器,它假设在192个线程和
min(8*148999*8999)
块的情况下提供最高性能,但由于某些原因,它没有提供正确的结果共享内存减少需要每个块两个线程的能力。请原谅我的提问,但这段代码是你自己写的,还是你从其他地方得到的?您在这里询问的一切似乎都源于对代码实际功能的基本理解不足。英伟达的例子有一个优秀的白皮书M·夏里斯在CUDA实现的还原。阅读并研究其中包含的代码示例可能会让您受益匪浅。对于9000*9000输入数组,运行此内核完全不需要运行9000*9000线程。也不需要修改它来使用2D网格。@Talonmes,请你进一步解释一下好吗?这听起来很有趣,带有网格步长的while循环旨在能够累积任意长度的输入数组的部分和。这就是把循环放在首位的全部意义…@Talonmes我已经照你说的做了。谢谢。现在没事了。但是我注意到,当使用192个线程和
min(8*148999*8999)
块时,正确性并不好,但如果使用128个线程和
min(8*148999*8999)
块,则正确性是完美的。你对此有什么解释吗?根据CUDA占用率计算器,它假设在192个线程和
min(8*148999*8999)
块的情况下提供最高性能,但由于某些原因,它没有提供正确的结果共享内存减少需要每个块两个线程的能力。请原谅我的提问,但这段代码是你自己写的,还是你从其他地方得到的?您在这里询问的一切似乎都源于对代码实际功能的基本理解不足。英伟达的例子有一个优秀的白皮书M·夏里斯在CUDA实现的还原。您可能会从阅读和研究其中包含的代码示例中获益。