两个1D向量点积的约简算法

时间:2015-11-12 07:14:49

标签: cuda

我一直试图通过减少来计算出一个算法来获得CUDA程序中两个向量的点积,并且似乎被卡住了:/

本质上,我正在尝试用CUDA编写这段代码:

for (int i = 0; i < n; i++)
    h_h += h_a[i] * h_b[i];

其中h_ah_b是浮点数组,h_h总结点积。

我正在尝试使用减少 - 到目前为止我已经有了这个...

__global__ void dot_product(int n, float * d_a, float * d_b){

     int i = threadIdx.x;

     for (int stride = 1; i + stride < n; stride <<= 1) {
         if (i % (2 * stride) == 0){
             d_a[i] += d_a[i + stride] * d_b[i + stride];
         }
         __syncthreads();
     }
}

如果我将主线更改为d_a[i] += d_a[i + stride];,它会很好地总结阵列。从我收集的内容来看,我似乎遇到了一个并行的问题。有人可以指出我的问题吗?

我的内核调用是:

dot_product<<<1, n>>>(n, d_a, d_b);,其中n是每个数组的大小。

1 个答案:

答案 0 :(得分:2)

这里有两个问题:

  1. 正如评论中所指出的,你永远不会计算出第一个元素的产品(这是一个小问题)
  2. 您的点积计算不正确。并行减少应该执行相应元素的各个产品的总和。您的代码会在并行缩减的每个阶段执行产品,以便产品在求和时再次成倍增加。这是不正确的。
  3. 你想做这样的事情:

    __global__ void dot_product(int n, float * d_a, float * d_b){
    
         int i = threadIdx.x;
    
         d_a[i] = d_a[i] * d_b[i]; // d_a now contains products
         __syncthreads();
    
         for (int stride = 1; i + stride < n; stride <<= 1) {
             if (i % (2 * stride) == 0){
                 d_a[i] += d_a[i + stride]; // which are summed by reduction
             }
             __syncthreads();
         }
    }
    

    [免责声明:用浏览器编写,绝不编译或测试,自担风险使用]