【问题标题】:CUDA synchronization and reading global memoryCUDA同步和读取全局内存
【发布时间】:2012-01-04 07:05:05
【问题描述】:

我有这样的事情:

__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;
}

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

【问题讨论】:

  • __syncthreads 是块级同步原语,而不是网格级。根据您最后几个问题,您似乎应该花点时间阅读 CUDA 文档。
  • 好的,所以无法阅读?
  • @sidyll:CUDA 是 C。留下 C 标签。

标签: cuda


【解决方案1】:

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

您可以做的一件事是使用__shared__ CUDA 指令创建共享线程本地存储,该指令允许您的块中的线程在它们之间共享信息,但阻止其他块的线程访问分配给当前块。一旦块内的计算完成(并且您可以使用__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;        
}

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

【讨论】:

  • 警告,这是危险代码。编译器可能会选择重新排序对标志和 arr 的写入,从而导致竞争条件。您可能应该需要一个 __threadfence() 才能正确。一般来说,没有原子的块间通信必须小心,如果有的话——通常你应该找到另一种方式......
  • 感谢__threadfence 上的信息。我已将其添加到代码中,并且根据 Nvidia 文档应该可以正常工作。由于只有一个线程正在写入一个标志(每个线程都有一个标志),我认为不需要原子操作。
  • @Jason:您的第二个代码假定线程idx 与线程idx+1 同时调度和运行。 CUDA 执行模型中没有任何东西可以保证这一点。抱歉,该代码已损坏,在容易证明的情况下会死锁。
  • 好吧,我没有意识到 CUDA 运行时。我已经更改了答案以反映这一点。如果您发现有问题,我将不胜感激。
猜你喜欢
  • 2013-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-17
  • 2014-07-21
  • 1970-01-01
相关资源
最近更新 更多