单线程内CUDA内存操作顺序

标签 cuda

来自 CUDA 编程指南(v. 5.5):

The CUDA programming model assumes a device with a weakly-ordered memory model, that is:

  • The order in which a CUDA thread writes data to shared memory, global memory, page-locked host memory, or the memory of a peer device is not necessarily the order in which the data is observed being written by another CUDA or host thread;
  • The order in which a CUDA thread reads data from shared memory, global memory, page-locked host memory, or the memory of a peer device is not necessarily the order in which the read instructions appear in the program for instructions that are independent of each other

但是,我们能否保证从单个线程看到的(依赖的)内存操作实际上是一致的?如果我这样做 - 说:

arr[x] = 1;
int z = arr[y];

其中 x 恰好等于 y,并且没有其他线程正在接触内存,我是否可以保证z 是 1?或者我还需要在这两个操作之间放置一些 volatile 或屏障吗?


回应 Orpedo 的回答

If your compiler doesn't compile the functionality stated by your code into equal functionality in machine-code, the compiler is either broken or you haven't taken the optimizations into consideration...

我的问题是允许哪些优化(由编译器或硬件完成)? 可能会发生这种情况 --- 例如 --- store 指令是非阻塞的,而后面的 load 指令以某种方式由内存 Controller 管理更快 比已经排队的存储

我不了解 CUDA 硬件。我是否可以保证上述情况永远不会发生?

最佳答案

CUDA 编程指南简单地指出,您无法预测线程的执行顺序,但每个线程仍将作为顺序线程运行。 在您所说的示例中,其中 x 和 y 相同并且没有其他线程接触内存,您可以保证 z = 1。 这里的要点是,如果您有多个线程对相同数据(例如数组)执行操作,则不能保证线程 #9 在 #10 之前执行。

举个例子:

__device__ void sum_all(float *x, float *result, int size N){
  x[threadId.x] = threadId.x;
  result[threadId.x] = 0;
  for(int i = 0; i < N; i++)
    result[threadId.x] += x[threadID.x];
}

这里我们有一些愚蠢的函数,它应该用 m ... n 中的数字填充共享数组(x)(从一个数字读取到另一个数字),然后将已经放入数组中的数字相加,将结果存储在另一个数组中。 鉴于您的最低索引线程是枚举线程 #0,您会期望代码第一次运行此代码 x 应包含

x[] = {0, 0, 0 ... 0} 且结果[] = {0, 0, 0 ... 0}

线程 #1 的下一个

x[] = {0, 1, 0 ... 0} 且结果[] = {0, 1, 0 ... 0}

线程 #2 的下一个

x[] = {0, 1, 2 ... 0} 且结果[] = {0, 1, 3 ... 0}

等等。 但这并不能保证。你无法知道是否例如线程 #3 首先运行,因此在线程 #0 运行之前更改数组 x[]。实际上,您甚至不知道在执行代码时数组是否被其他线程更改。

关于单线程内CUDA内存操作顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21205155/

相关文章:

CUDA nvcc 编译器设置 Ubuntu 12.04

c++ - 为什么cuda内核可以访问主机内存?

c++ - 即使在初始化结果参数后,CUDA atomicAdd 也会产生错误的结果

c++ - gpu::morphologyEx 在 CPU 中比 morphologyEx 慢?

c++ - 在 cuda 主机代码中使用 openMP?

iterator - CUDA Thrust sort_by_key 当键是由 zip_iterator 用自定义比较谓词处理的元组时

cuda - cuBLAS argmin -- 如果输出到设备内存会出现段错误吗?

c++ - 为什么更改 block 和网格大小会对运行时产生如此大的影响?

每个 block 的CUDA线程限制

python - 如何在 Linux 中分析 PyCuda 代码?