#define dimG 16
#define dimB 64
// slovebyGPU
__global__ void SloveStepGPU(float* X, float* Y, int * iCons, int* jCons, int * dCons, float* wCons, int cnt, float c)
{
int id = blockDim.x * blockIdx.x + threadIdx.x;
for (int i = id; i<cnt; i += dimG*dimB) {
int I = iCons[i];
int J = jCons[i];
int d = dCons[i];
float wc = 1.0f*wCons[i]*c;
if (wc > 1.0)wc = 1.0;
float XI = atomicAdd(&(X[I]), 0);
float XJ = atomicAdd(&(X[J]), 0);
float YI = atomicAdd(&(Y[I]), 0);
float YJ = atomicAdd(&(Y[J]), 0);
float pqx = XI - XJ;
float pqy = YI - YJ;
float mag = sqrtf(pqx*pqx + pqy*pqy);
float r = 1.0f*(d - mag) / 2;
float mx = wc * r * pqx / (mag + eps);
float my = wc * r * pqy / (mag + eps);
if (d == 1) {
atomicAdd(&(X[I]), mx);
atomicAdd(&(Y[I]), my);
}
atomicAdd(&(X[J]), -mx);
atomicAdd(&(Y[J]), -my);
}
在这段代码中,我知道X,Y可能存在数据竞争。我以前的想法是:允许读取XI,XJ,YI,YJ可能不是最新数据。但是,我发现在数据竞争过程中,它可能导致XI,XJ,YI,YJ 读取随机内存值。也就是说,内存访问冲突。即使在读写过程中添加了锁,我仍然可以获得相同的结果。只有减小dimB和dimG的大小以使几乎没有数据争用时,我才能获得正确的结果。有什么解决办法吗?
我在Windows + vs2015 + cuda9.1环境下使用64位编译。
但是,我在linux下使用了相同的代码,却没有发现问题。
在Windows下使用nsight cuda调试器时没有问题。原因可能是与调试器一起运行很慢,并且不会引起数据争用。
-------更新行----- 删除其他代码
答案 0 :(得分:0)
问题出现在此if (d == 1)
中,我用设备功能if
,fminf
代替了fmaxf
以解决该问题。我猜想该分支是在同一经线中进入的,并且存在数据竞争并且某些进程被挂起,这引起了奇怪的问题。
if (d == 1) {
atomicAdd(&(X[I]), mx);
atomicAdd(&(Y[I]), my);
}
到
float fd = fmaxf(2.0f - d, 0.0f);
X[I] += fd * 1.0f * mx;
Y[I] += fd * 1.0f * my;