使用__sync CUDA和全局内存

时间:2013-09-17 18:23:14

标签: cuda

我正在尝试实现异步PSO。我这样做的方法如下:

__global__ void particle(double *pos, double *pbest, double *vpbest, double *vel, double *gbest){

    int thread = threadIdx.x + blockDim.x * blockIdx.x;
    int particle, i = 0;
    double tpbest;

    double l, r;
    int index, best, j;

    if(thread < DIMPAR){
      particle = thread / NDIM;
        do{
            best    = ring(vpbest, &particle);

            index = (best * NDIM) + (thread % NDIM);

            l = (double) 2.05 * (double) uniform(thread) * ( pbest[thread] -   pos[thread] );
            r = (double) 2.05 * (double) uniform(thread) * ( pbest[index]  -   pos[thread] );

            vel[thread] = vel[thread] + l + r;

                pos[thread] =  pos[thread] + vel[thread];

                __syncthreads(); // I am trying wait all threads write in global memory

            if( (thread % NDIM) == 0 ){ //only one thread replace the vector
                tpbest = rastrigin(pos, particle * NDIM, NDIM);
                if(tpbest < vpbest[particle]){
                    vpbest[particle] = tpbest;
                    for(j = 0 ; j < NDIM; j++){
                        pbest[(particle * NDIM) + j] = pos[(particle * NDIM) + j];
                    }

                }
            }

            i++;
        }while(i < 10000);
    }
}
电话:

particle<<<1,512>>>(d_pos, d_pbest, d_vpbest, d_velo, d_gbest);

有时同步有问题... pos [thread]中的某些值会发散。 在B.6节CUDA_C_PROGRAMMING指南:

  

等待,直到线程块中的所有线程都到达此点   以及这些线程之前所做的所有全局和共享内存访问   __syncthreads()对块中的所有线程都是可见的。

pos vector就像这样:

p0 = [0,1,2] //粒子1

p1 = [3,4,5] //粒子2

p2 = [6,7,8] //粒子3

pos = [1,2,3,4,5,6,7,8] // pos vector,DIMPAR = 9; NPAR = 3; NDIM = 3

当我使用NDIM&gt; = 30时,发生分歧

如何使用全局内存确保同步?

1 个答案:

答案 0 :(得分:1)

您的 _ syncthread() 位于 if 语句中。如果块大小大于 DIMPAR ,请小心,程序将停止。要使 _syncthread()正常工作,块内的所有线程都必须能够访问它。

修改代码的一种方法如下(我不知道你的代码的目的,所以可能有更好的方法):

particle = thread / NDIM;
    do{
        if(thread < DIMPAR){
            best    = ring(vpbest, &particle);

            index = (best * NDIM) + (thread % NDIM);

            l = (double) 2.05 * (double) uniform(thread) * ( pbest[thread] -   pos[thread] );
            r = (double) 2.05 * (double) uniform(thread) * ( pbest[index]  -   pos[thread] );

            vel[thread] = vel[thread] + l + r;

            pos[thread] =  pos[thread] + vel[thread];
        }

        __syncthreads(); 

现在所有线程都可以达到同步点。 我在其余代码中注意到的另一个问题是,一个线程使NDIM在for循环中工作。相反,您可以将 tpbest 作为块的线程之间的共享变量(或数组)。然后,在再次同步线程之后,您可以在已经空闲的线程之间分配NDIM,而不是使用for循环,并使它们将效果一起写入全局内存。通过这种方式,访问速度会更快,并且可以合并。