CUDA同步和读取全局内存

nos*_*bor 5 cuda

我有这样的事情:

__global__ void globFunction(int *arr, int N) {
    int idx = blockIdx.x* blockDim.x+ threadIdx.x;
    // calculating and Writing results to arr ...
    __syncthreads();
    // reading values of another threads(ex i+1)
    int val = arr[idx+1]; // IT IS GIVING OLD VALUE
}


int main() {
    // declare array, alloc memory, copy memory, etc.
    globFunction<<< 4000, 256>>>(arr, N); 
    // do something ...
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

为什么我阅读时会得到旧的价值arr[idx+1]?我致电了__syncthreads,所以我希望看到更新后的值。我做错什么了?我正在读取缓存还是什么?

Jas*_*son 7

使用该__syncthreads()函数仅同步当前块中的线程。在这种情况下,这将是您启动内核时创建的每个块 256 个线程。因此,在给定的数组中,对于跨入另一个线程块的每个索引值,您最终将从全局内存中读取一个与当前块中的线程不同步的值。

为了避免此问题,您可以采取的一件事是使用 CUDA 指令创建共享线程本地存储,该__shared__指令允许块中的线程在彼此之间共享信息,但阻止其他块中的线程访问为当前块分配的内存。一旦块内的计算完成(并且您可以用于__syncthreads()此任务),您就可以将共享块级存储中的值复制回全局可访问的内存中。

你的内核可能看起来像这样:

__global__ void globFunction(int *arr, int N) 
{
    __shared__ int local_array[THREADS_PER_BLOCK];  //local block memory cache           
    int idx = blockIdx.x* blockDim.x+ threadIdx.x;

    //...calculate results
    local_array[threadIdx.x] = results;

    //synchronize the local threads writing to the local memory cache
    __syncthreads();

    // read the results of another thread in the current thread
    int val = local_array[(threadIdx.x + 1) % THREADS_PER_BLOCK];

    //write back the value to global memory
    arr[idx] = val;        
}
Run Code Online (Sandbox Code Playgroud)

如果必须跨块同步线程,则应该寻找另一种方法来解决问题,因为当问题可以分解为块时,CUDA 编程模型才能最有效地工作,并且线程同步只需要在块内进行。

  • 警告,这是危险代码。编译器可能会选择重新排序对 flags 和 arr 的写入,从而导致竞争条件。您可能应该需要一个 __threadfence() 才能正确。一般来说,没有原子的块间通信必须小心完成,如果有的话——通常你应该找到另一种方法...... (5认同)