cuda中循环全局缓冲区的原子操作

cuda中循环全局缓冲区的原子操作,cuda,atomic,circular-buffer,Cuda,Atomic,Circular Buffer,我正在实现一个循环全局内存,以使所有线程能够同时将数据读/写到同一个缓冲区。这是一个非常简单的cpu生产者/消费者算法。但我发现我的cuda代码有问题。 循环缓冲区的定义如下: #define BLOCK_NUM 1024 #define THREAD_NUM 64 #define BUFFER_SIZE BLOCK_NUM*THREAD_NUM*10 struct Stack { bool bDirty[BUFFER_SIZE]; unsigned int index;

我正在实现一个循环全局内存,以使所有线程能够同时将数据读/写到同一个缓冲区。这是一个非常简单的cpu生产者/消费者算法。但我发现我的cuda代码有问题。 循环缓冲区的定义如下:

#define BLOCK_NUM 1024
#define THREAD_NUM 64
#define BUFFER_SIZE BLOCK_NUM*THREAD_NUM*10
struct Stack {
    bool bDirty[BUFFER_SIZE];
    unsigned int index;
    unsigned int iStackSize;
}
读取设备实现为:

__device__ void read(Stack *pStack) {
    unsigned int index = atomicDec(&pStack->index, BUFFER_SIZE-1);
    if(- -index >= BUFFER_SIZE)
        index = BUFFER_SIZE - 1;
    // check
    if(pStack->bDirty[index] == false) {
        printf(“no data\n”);
        return;
    }
    //set read flag
    pStack->bDirty[index] = false;
    atomicSub(&pStack->iStackSize, 1);
}
写入设备功能是:

__device__ void write(Stack *pStack) {
    unsigned int index = atomicInc(&pStack->index, BUFFER_SIZE - 1);
    //check
    if(pStack->bDirty[index] == true) {
        printf(“why dirty\n”);
        return;
    }
    pStack->bDirty[index] = true;
    atomicAdd(&pStack->iStackSize, 1);
}
为了以更健壮的方式测试读/写函数,我编写了以下内核:

__global__ void kernelWrite(Stack *pStack) {
    if(threadIdx.x != 0) //make write less than thread number for testing purpose
        write(pStack);
}

__global__ void kernelRead(Stack *pStack) {
    read(pStack);
    __syncthreads();
    if(threadIdx.x % 3 != 0) // make write less than read
        write(pStack);
    __syncthreads();
}
在main函数中,我使用了一个死循环来测试读/写是否是原子的

int main() {
    Stack *pHostStack = (Stack*)malloc(sizeof(Stack));
    Stack *pStack;
    cudaMalloc(&pStack, sizeof(Stack));
    cudaMemset(pStack, 0, sizeof(Stack));

    while(true) { //dead loop
        kernelWrite<<<BLOCK_NUM, THREAD_NUM>>>(pStack);
        cudaDeviceSynchonize();
        cudaMemcpy(pHostStack, pStack, sizeof(Stack), cudaMemcpyDeviceToHost);
        while(pHost->iStackSize >= BLOCK_NUM*THREAD_NUM) {
             kernelRead<<<BLOCK_NUM, THREAD_NUM>>>(pStack);
                   cudaDeviceSynchonize();
                   cudaMemcpy(pHostStack, pStack, sizeof(Stack), cudaMemcpyDeviceToHost);
         }
    return 0;
}
intmain(){
Stack*pHostStack=(Stack*)malloc(sizeof(Stack));
堆栈*pStack;
cudaMalloc(&pStack,sizeof(Stack));
cudaMemset(pStack,0,sizeof(Stack));
while(true){//死循环
内核写入(pStack);
CUDADeviceSynchronize();
cudaMemcpy(pHostStack、pStack、sizeof(Stack)、cudaMemcpyDeviceToHost);
而(pHost->iStackSize>=块数*线程数){
内核读取(pStack);
CUDADeviceSynchronize();
cudaMemcpy(pHostStack、pStack、sizeof(Stack)、cudaMemcpyDeviceToHost);
}
返回0;
}
当我执行上述代码时,我得到错误消息“why dirty”和“no data”。读/写逻辑有什么问题


顺便说一句,我没有将线程ID映射到线性缓冲区地址,因为在我的应用程序中,可能只有10%的线程写入缓冲区,这是不可预测的/随机的。

关键问题是,由于读取和写入同一缓冲区,原子操作不是真正的原子操作。奇怪的是,当总线程数为ss then 4096,不会显示任何错误消息。

在您使用之前,我没有看到任何初始化
pStack
内容的代码。它存在吗?如果您发布一个适当的抱歉,会简单得多,我忘了设置它,因为代码是通过我的手机上传的,而不是从pc上传的。@Talonmes是的,memset存在于我的可运行程序中我。这个演示是完整的,除了一些标题包括和