执行期间cuda执行块是否会被中断?

时间:2016-02-20 00:51:37

标签: c++ cuda

我担心我的一个cuda内核中存在潜在的竞争状况。我正在为Barnes Hunt Tree算法开发一个N-Body模拟器。此内核的目的是计算树的每个分支的总质量和质心。我想"迭代"在容器数组上以相反的顺序,因为最后分配的那些最不可能依赖于其他子容器,所以数组中的第一个容器可能依赖于后面的容器。

我正在使用原子计数器来跟踪哪些块首先开始,第一个块处理前几个容器,依此类推。我担心的是,块的执行暂时可以暂停,直到其他块完成或类似的东西?这是一个问题,因为说第一个块开始然后由于某种原因为其他块收益。在这种情况下,如果其他人依赖于第一个块执行的计算,则它们将无限循环。

__global__ void compute_mass_centers_kernel()
{
    int blockNum = atomicAdd(&dev::block_number, 1);
    int cindex = dev::ncontainers - blockNum * blockDim.x - 1 - threadIdx.x;
    if(cindex < 0)
        return;

    Container& c = dev::containers[cindex];
    int missing_ptrs[8];
    int missing = 0;

    float total_mass = 0.0f;
    double3 com = {0}; 
    for(int i = 0; i < 8; i++)
    {
        if(c[i] > 1)
        {
            Object& o = objat(c[i]);
            total_mass += o.m;
            com.x += (double)o.p.x * o.m;
            com.y += (double)o.p.y * o.m;
            com.z += (double)o.p.z * o.m;
        }
        else if(c[i] < 1)
        {
            missing_ptrs[missing++] = c[i];
        }
    }

    while(missing)
    {
        for(int i = 0; i < missing; i++)
        {
            Container& c2 = ctrat(missing_ptrs[i]);
            if(c2.total_mass >= 0.0f)
            {
                total_mass += c2.total_mass;
                com.x += (double)c2.center_of_mass.x * c2.total_mass;
                com.y += (double)c2.center_of_mass.y * c2.total_mass;
                com.z += (double)c2.center_of_mass.z * c2.total_mass;
                missing_ptrs[i--] = missing_ptrs[--missing];
            }
        }
    }

    c.center_of_mass.x = com.x / total_mass;
    c.center_of_mass.y = com.y / total_mass;
    c.center_of_mass.z = com.z / total_mass;
    c.total_mass = total_mass;
}

void compute_mass_centers()
{
    int threads, blocks;
    cudaOccupancyMaxPotentialBlockSize(&blocks, &threads, compute_mass_centers_kernel, 0, 0);
    cucheck();

    int ncontainers;
    cudaMemcpyFromSymbol(&ncontainers, dev::ncontainers, sizeof(int), 0, cudaMemcpyDeviceToHost);
    cucheck();

    blocks = (ncontainers + (threads - 1)) / threads;

    cudaMemcpyToSymbol(dev::block_number, &ZERO, sizeof(int), 0, cudaMemcpyHostToDevice);
    cucheck();

    compute_mass_centers_kernel<<< blocks, threads >>>();
    cucheck();
}

1 个答案:

答案 0 :(得分:1)

没有类似CUDA块间同步的东西。然而,人们已经对此进行了研究,例如:Shucai Xiao and Wu-chun Feng块间GPU通信 通过快速障碍同步

在你的情况下,你可以简单地对每个块执行几次内核调用,或者如果你冒险在全局内存中进行同步的自制(慢)阻塞原子操作。

对于您的潜在问题,最佳解决方案可能是使用cuda-memcheck检查您的代码。