如何对CUDA内核内部的结构进行原子操作?

如何对CUDA内核内部的结构进行原子操作?,cuda,Cuda,我有下面的一段代码,我正在尝试递增名为SL的结构。在下面的情况下,如何以原子方式递增相同的结构?如何避免比赛状态?我不关心在这种情况下实现的并行化 __global__ void insertKernel(struct SlabList* head_ref, int* new_key, int* new_val, int size,struct SlabList* SL, struct SlabList* temp){ int id = blockIdx.x*blockDim.x + thre

我有下面的一段代码,我正在尝试递增名为SL的结构。在下面的情况下,如何以原子方式递增相同的结构?如何避免比赛状态?我不关心在这种情况下实现的并行化

__global__ void insertKernel(struct SlabList* head_ref, int* new_key, int* new_val, int size,struct SlabList* SL, struct SlabList* temp){
 int id = blockIdx.x*blockDim.x + threadIdx.x;
        if(id<size/SLAB_SIZE){
        head_ref=NULL;
        struct SlabList* new_node = (struct SlabList*) 
        malloc(sizeof(struct SlabList));
        for(int j=0;j<SLAB_SIZE;j++){
               new_node->key[j] = new_key[id*SLAB_SIZE+j];
               new_node->val[j]= new_val[id*SLAB_SIZE+j];
        }
        new_node->next = head_ref;
        memcpy(SL,new_node, size * sizeof(struct SlabList));
        head_ref    = new_node;
        SL++;//How to perform this atomically?
}
\uuuuu全局\uuuuuuvoid insertKernel(struct SlabList*head\u ref,int*new\u key,int*new\u val,int size,struct SlabList*SL,struct SlabList*temp){
int id=blockIdx.x*blockDim.x+threadIdx.x;
如果(idval[j]=新的[id*板尺寸+j];
}
新建节点->下一步=头部\u参考;
memcpy(SL,新的_节点,大小*sizeof(struct SlabList));
head\u ref=新节点;
SL++;//如何以原子方式执行此操作?
}

我查看了CUDA的
atomicInc
atomicAdd
API,但无法继续,因为它们采用了不同的参数。

据我估计,有两种操作只有在以原子方式执行(不改变代码结构)的情况下才能正常工作--突出显示的
SL
的增量,以及随着树的展开而交换的
head\u ref
指针值

如果(且仅当)您使用的是64位操作系统,那么类似的操作系统可能会起作用:

__global__ void insertKernel(struct SlabList* head_ref, int* new_key, 
                             int* new_val, int size, struct SlabList* SL, struct SlabList* temp)
{
    int id = blockIdx.x*blockDim.x + threadIdx.x;
    if(id<size/SLAB_SIZE){
        struct SlabList* new_node = (struct SlabList*)malloc(sizeof(struct SlabList));
        SlabList* SLnew = (SlabList *)atomicAdd((unsigned long long *)&SL,
                                                sizeof(struct SlabList));
        SlabList* oldhead = (SlabList *)atomicExch((unsigned long long *)&head_ref, 
                                        (unsigned long long)new_node);
        for(int j=0;j<SLAB_SIZE;j++){
            new_node->key[j] = new_key[id*SLAB_SIZE+j];
            new_node->val[j] = new_val[id*SLAB_SIZE+j];
        }
        new_node->next = oldhead;
        memcpy(SLnew, new_node, sizeof(struct SlabList));
    }
}
\uuuuu全局\uuuuuuuvoid insertKernel(struct SlabList*head\u ref,int*new\u key,
int*新值,int大小,结构SlabList*SL,结构SlabList*temp)
{
int id=blockIdx.x*blockDim.x+threadIdx.x;
如果(idval[j]=新的[id*板尺寸+j];
}
新建节点->下一步=旧头;
memcpy(SLnew,new_节点,sizeof(struct SlabList));
}
}

[注意:从未编译或运行过,更不用说测试了。请自行承担使用风险]

您显示的代码并不是试图对结构执行原子操作,而是试图对指针执行原子操作,这很简单
atomicAdd((unsigned long long*)&SL,sizeof(SL[0])
这假设您在64位操作系统上运行。还要注意,
head\u ref
上的操作也是一种内存竞争,需要以原子方式进行处理,这样代码才有机会正确工作在考虑了一段时间后,我意识到我之前的评论,虽然可能是“技术上的”正确,可能不会产生预期效果,因为
SL
指针是一个单独填充到所有线程的数量。它不是“全局”实体。当一个线程“更新”时这对其他线程复制
SL
没有影响。对于
head\u ref
也是如此。这可能应该使用不同的方法来解决,例如网格跨步循环,其中每个线程都可以事先知道在没有原子的情况下为其保留的位置。