CUDA dot产品给出了错误的结果

时间:2018-05-28 04:02:44

标签: cuda gpu

我用CUDA写了一个点积产品代码来计算两个双向量的点积。内核由N个线程(N <1024)1块调用。但它无法给出正确的结果。我无法理解。

__global__ void dotthread(double* a, double *b,double *sum, int N)
  {
    int tid = threadIdx.x;  
    sum[0] = sum[0]+a[tid] * b[tid];  //every thread write to the sum[0] 
   __syncthreads();  
  }

2 个答案:

答案 0 :(得分:1)

让我们看看你的三行代码中的两行:

    sum[0] = sum[0]+a[tid] * b[tid];  //every thread write to the sum[0] 
    __syncthreads();  

第一行包含记忆竞赛。块中的每个线程将同时尝试写入sum [0]。 cuda执行模型中没有任何内容可以阻止这种情况发生。没有自动序列化或内存保护可以阻止此行为。

第二行是指令障碍。这意味着线程的每个经线都将被阻塞,直到线程的每个经线都到达屏障。它对先前的指令没有任何影响,它对内存一致性或代码发出的任何内存事务的行为都没有任何影响。

你写的代码是不可逆转的。执行此类操作的规范方法是通过并行缩减。有许多不同的方法可以做到这一点。它可能是GPU描述和描述最多的并行算法。你已经安装了CUDA工具包,你已经有了一个完整的工作示例和一个描述算法的综合论文,因为它将使用共享内存实现。我建议你研究一下。

你可以看到使用共享内存here的点积的(几乎)工作实现,我建议你研究它。您还可以在库中找到并行块缩减的最佳实现,例如cub

答案 1 :(得分:-1)

我写了两个版本的dot产品程序。第一个使用atomiAdd函数,第二个为每个块分配一个共享变量。    计算时间分别为3.33 ms和0.19 ms,相比之下,还原点积和单线点积为0.17 ms和411.43 ms。

GPU Device 0: "GeForce GTX 1070 Ti" with compute capability 6.1
2000000flow array allocated 2147483647
 naive elapsedTimeIn Ms 411.437042 Ms
sum is 6.2831853071e+06

thread atomic add elapsedTimeIn Ms 3.3371520042 Ms
sum is 6.2831853071e+06

 cache reduction elapsedTimeIn Ms 0.1764480025 Ms
sum is 6.2831853072e+06

 cache atomicadd elapsedTimeIn Ms 0.1914239973 Ms
sum is 6.2831853072e+06

__global__ void dotatomicAdd(double* a, double *b,double *sum, int N)
{
    int tid = blockDim.x * blockIdx.x + threadIdx.x;
    while (tid < N){
        double t=a[tid] * b[tid];
        atomicAdd(sum,t);
        tid+=blockDim.x * gridDim.x;
    }
}


__global__ void dotcache(double* a, double *b,double *c, int N)
{

    __shared__ double cache;
    int tid = threadIdx.x + blockIdx.x * blockDim.x;
    int cacheIndex = threadIdx.x;
    double  temp = 0.0;
    cache=0.0;
    __syncthreads();

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

    if (cacheIndex == 0) c[blockIdx.x] = cache;
}