尽管使用atomicAdd函数(CUDA),竞争条件?

时间:2013-05-16 04:16:53

标签: c cuda atomic race-condition

我有一个问题在两个层面上是平行的:我有很多(x0, x1, y0, y1)个坐标对,它们变成了变量vdx, vdy, vyy,对于每个集合,我都试图计算由它们组成的所有“单项式”的值,最大程度为 n (即它们的不同幂的所有可能组合,如vdx^3*vdy*vyy^2vdx*1*vyy^4)。然后将这些值加到所有集合上。

我的策略(现在我只想让它工作,它不需要用多个内核或复杂的减少进行优化,除非真的必须)是让每个线程处理一个集合坐标对,并计算所有相应单项式的值。每个块的共享内存保存所有单项和,当块完成时,块中的第一个线程将结果添加到全局和。由于每个块的共享内存都被所有地方的所有线程访问,我使用的是atomicAdd;与块和全局内存相同。

不幸的是,某些地方似乎仍然存在竞争条件,因为每次运行内核时都会出现不同的结果。

如果有帮助,我现在正在使用degree = 3并省略其中一个变量,这意味着在下面的代码中,最里面的for循环(超过evbl)没有做任何事情,重复4次。实际上,内核的输出看起来像这样:51502,55043.1,55043.1,51502,47868.5,47868.5,48440.5,48440.6,46284.7,46284.7,46284.7,46284.7,46034.3,46034.3,46034.3,46034.3,44972.8,44972.8,44972.8,44972.8,43607.6,43607.6,43607.6,43607.6,43011,43011,43011,43011,42747.8,42747.8,42747.8,42747.8,45937.8,45937.8,46509.9,46509.9,...并且有一个(粗略的)4元组模式是值得注意的。但每次我运行它时,值都非常不同。

一切都在漂浮,但我在2.1 GPU上,所以这应该不是问题。 cuda-memcheck也报告没有错误。

有更多CUDA经验的人能否给我一些指示如何追踪这里的竞争状况?

__global__ void kernel(...) {

  extern __shared__ float s_data[];

  // just use global memory for now
  // get threadID:
  int idx = blockIdx.x * blockDim.x + threadIdx.x;
  if(idx >= nPairs) return;

  // ... do some calculations to get x/y...

  // calculate vdx, vdy and vyy
  float vdx = (x1 - x0)/(float)xheight;
  float vdy = (y1 - y0)/(float)xheight;
  float vyy =  0.5*(y0 + y1)/(float)xheight;


  const int offs1 = degree + 1;
  const int offs2 = offs1 * offs1;
  const int offs3 = offs2 * offs1;
  float sol = 1.0;

  // now calculate monomial results and store in shared memory

  for(int evdx = 0; evdx <= degree; evdx++) {
    for(int evdy = 0; evdy <= degree; evdy++) {
      for(int evyy = 0; evyy <= degree; evyy++) {
        for(int evbl = 0; evbl <= degree; evbl++) {
          s = powf(vdx, evdx) + powf(vdy, evdy) + powf(vyy, evyy);
          atomicAdd(&(s_data[evbl + offs1*evyy + offs2*evdy +
                offs3*evdx]), sol/1000.0 ); 

        }
      }
    }
  }

  // now copy shared memory to global
  __syncthreads();
  if(threadIdx.x == 0) {
    for(int i = 0; i < nMonomials; i++) {
      atomicAdd(&outmD[i], s_data[i]);
    }
  }
}

1 个答案:

答案 0 :(得分:4)

您正在使用共享内存,但您永远不会初始化它。