CUDA在内核中递增全局设备计数器

时间:2016-02-27 18:47:17

标签: cuda

我正在尝试找出一个简单的CUDA设计问题的解决方案。假设我有一个处理数据的内核。如果当前处理的数据满足指定条件,则outputArray中的相应元素将获得当前计数器值,并且计数器正在递增。

看起来像是:

__global__ void setTags(INDATA* inputData, int* tags)
{
    int blockId = blockIdx.x + blockIdx.y * gridDim.x;
    int threadId = blockId * (blockDim.x * blockDim.y) + (threadIdx.y * blockDim.x) + threadIdx.x;
    if(threadId < N)
    {
        INDATA current = inputData[threadId];
        if(/* current meets some criteria */)
        {
            tags[threadId] = /*current counter value */
            /* increment counter value */
        }
    }
}

符合标准的元素数量明显少于所有元素。重点是处理停留在GPU上,我的案例标记为唯一整数,范围从0到满足条件的案例数量 - 1.有没有比单线程中增量更快的方法呢?

1 个答案:

答案 0 :(得分:5)

听起来你想要的是atomicAdd函数来递增一些全局计数器,它可以被许多线程同时访问。你可以这样:

__device__ int counter; // initialise before running kernel

__global__ void setTags(INDATA* inputData, int* tags)
{
    int blockId = blockIdx.x + blockIdx.y * gridDim.x;
    int threadId = blockId * (blockDim.x * blockDim.y) + 
                   (threadIdx.y * blockDim.x) + threadIdx.x;
    if(threadId < N)
    { 
        INDATA current = inputData[threadId];
        if(/* current meets some criteria */)
        {
            int current_val = atomicAdd(&counter, 1);
            tags[threadId] = current_val;
        }
    }
}

这里,atomicAdd将原子地读取counter的值,并在单个原子操作中将其递增1。如果总增量操作的数量不是太大,那么这将是高效的。但是,因为操作序列化执行,如果您启动的大量线程将访问并递增全局计数器,您可能会寻找另一种方法。