You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用atomicCAS实现CUDA互斥锁的行为咨询

使用atomicCAS实现CUDA互斥锁的行为咨询

最近我在学习CUDA编程,尝试用atomicCAS函数实现一个互斥锁,让所有线程依次访问并递增一块共享数据。下面是我写的代码和对应的运行结果,想和大家交流下这个实现的行为是否符合预期,或者有没有可以优化的地方~

实现代码

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include "book.h"
#include <time.h>

// 全局变量:0表示未锁定,1表示锁定
__device__ int lock;

__global__ void mykernel(float* data){
    int i = threadIdx.x + blockIdx.x * blockDim.x;
    int stride = blockDim.x * gridDim.x;

    do {
        __syncthreads(); 
        // __threadfence();
        printf("Thread %d of block %d waiting since lock value is %d...\n", threadIdx.x, blockIdx.x, lock);
    } while(atomicCAS(&lock,0,1));

    printf("Locked!\n");
    data[0] += 1;
    printf("Now data is %f\n", data[0]);

    __threadfence(); // 等待写入操作完成
    lock = 0;
    __threadfence(); // 等待写入操作完成
    printf("Unlocked!\n");
}

int main(void) {
    float* d_data;
    float *h_data;
    int n_block = 4;
    int n_thread_per_block = 4;

    // 初始化共享数据
    h_data = (float*) malloc(sizeof(float));
    h_data[0] = 0;

    // 初始化互斥锁
    cudaMemset((int*) lock, 0, sizeof(int));
    printf("Inital value of lock is: %d\n", lock);

    HANDLE_ERROR(cudaMalloc((void**)&d_data, sizeof(float)));
    HANDLE_ERROR(cudaMemcpy(d_data, h_data, sizeof(float), cudaMemcpyHostToDevice));

    mykernel <<<n_block, n_thread_per_block>>> (d_data);
}

运行结果

Inital value of lock is: 0
Thread 0 of block 2 waiting since lock value is 0...
Thread 1 of block 2 waiting since lock value is 0...
Thread 2 of block 2 waiting since lock value is 0...
Thread 3 of block 2 waiting since lock value is 0...
Thread 0 of block 1 waiting since lock value is 0...
Thread 1 of block 1 waiting since lock value is 0...
Thread 2 of block 1 waiting since lock value is 0...
Thread 3 of block 1 waiting since lock value is 0...
Thread 0 of block 3 waiting since lock value is 0...
Thread 1 of block 3 waiting since lock value is 0...
Thread 2 of block 3 waiting since lock value is 0...
Thread 3 of block 3 waiting since lock value is 0...
Thread 0 of block 0 waiting since lock value is 0...
Thread 1 of block 0 waiting since lock value is 0...
Thread 2 of block 0 waiting since lock value is 0...
Thread 3 of block 0 waiting since lock value is 0...
Locked!
Thread 0 of block 3 waiting since lock value is 1...
Thread 1 of block 3 waiting since lock value is 1...
Thread 2 of block 3 waiting since lock value is 1...
Thread 3 of block 3 waiting since lock value is 1...
Thread 0 of block 1 waiting since lock value is 1...
Thread 1 of block 1 waiting since lock value is 1...
Thread 2 of block 1 waiting since lock value is 1...
Thread 3 of block 1 waiting since lock value is 1...
Thread 0 of block 0 waiting since lock value is 1...
Thread 1 of block 0 waiting since lock value is 1...
Thread 2 of block 0 waiting since lock value is 1...
Thread 3 of block 0 waiting since lock value is 1...
Now data is 1.000000
Thread 0 of block 3 waiting since lock value is 1...
Thread 1 of block 3 waiting since lock value is 1...
Thread 2 of block 3 waiting since lock value is 1...
Thread 3 of block 3 waiting since lock value is 1...
Thread 0 of block 1 waiting since lock value is 1...
Thread 1 of block 1 waiting since lock value is 1...
Thread 2 of block 1 waiting since lock value is 1...
Thread 3 of block 1 waiting since lock value is 1...
Thread 0 of block 0 waiting since lock value is 1...
Thread 1 of block 0 waiting since lock value is 1...
Thread 2 of block 0 waiting since lock value is 1...
Thread 3 of block 0 waiting since lock value is 1...
Unlocked!
Locked!
Thread 0 of block 3 waiting since lock value is 1...
Thread 1 of block 3 waiting since lock value is 1...
Thread 2 of block 3 waiting since lock value is 1...
Thread 3 of block 3 waiting since lock value is 1...
Thread 0 of block 0 waiting since lock value is 1...
Thread 1 of block 0 waiting since lock value is 1...
Thread 2 of block 0 waiting since lock value is 1...
Thread 3 of block 0 waiting since lock value is 1...
Now data is 2.000000
Thread 1 of block 2 waiting since lock value is 1...
Thread 2 of block 2 waiting since lock value is 1...
Thread 3 of block 2 waiting since lock value is 1...
Thread 0 of block 3 waiting since lock value is 1...
Thread 1 of block 3 waiting since lock value is 1...
Thread 2 of block 3 waiting since lock value is 1...
Thread 3 of block 3 waiting since lock value is 1...
Thread 0 of block 0 waiting since lock value is 1...
Thread 1 of block 0 waiting since lock value is 1...
Thread 2 of block 0 waiting since lock value is 1...
Thread 3 of block 0 waiting since lock value is 1...
Unlocked!
Locked!
Thread 1 of block 2 waiting since lock value is 1...
Thread 2 of block 2 waiting since lock value is 1...

从运行结果来看,线程确实是依次获取锁、修改共享数据、释放锁,数据也能正确递增,整体行为符合我的预期。不过我还是有点疑问:比如__syncthreads在这里的作用是否必要?还有__threadfence的使用是否足够严谨?有没有什么潜在的线程安全问题我没考虑到?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 13:24:29