3

作为我的问题的快速背景,对于 x86,可以保证对于 32 位字对齐的 4 字节或对于 64 位字对齐的 8 字节的单个内存访问将是原子的。因此,您可以创建“良性数据竞争”,其中至少一个线程写入内存地址,而另一个线程从同一地址读取,并且读者不会看到不完整写入的结果。读取线程将看到写入的整个效果,或者不会。

CUDA 编程模型中创建这些“良性”数据竞争条件的要求是什么?例如,如果两个独立的线程从两个不同的 SM 上的两个独立但同时运行的块将 64 位值写入相同的全局内存地址,则每个线程都会原子地写入它们的整个 64 位值,而第三个观察者只读回完全更新的 64 位内存块?或者写入会以更小的粒度进行,因此如果第三个观察者在两个线程同时写入后尝试从内存地址读回,则只会看到部分写入?

我知道竞争条件通常是要避免的,但是如果放宽内存排序的要求,则无需显式使用原子读/写函数。话虽如此,这取决于单个读/写的原子性是什么(即,多少位以及对齐方式)。有谁知道我在哪里可以找到这些信息?

4

1 回答 1

1

更新:@Heatsink 好心地通知我,确实可以通过使用该__threadfence()函数来强制实现一些内存一致性。

--

除非使用原子函数,否则 CUDA 在访问已由同一内核调用中调度的任何线程更新的全局内存时特别不保证任何一致性。只有读取由先前内核或内存副本写入的内存才是安全的。

因此,您不仅不能假设有关内存访问模式的任何事情——您甚至无法知道一个线程对全局内存所做的更新何时对另一个线程可见,或者实际上是否会变得可见。

当然,考虑到硬件在给定架构中的实现方式,您也许能够找到一种方法来实现线程之间的某种类型的非阻塞同步。但是,我真诚地怀疑是否有可能在区块之间安全地做到这一点。一个块中的线程所看到的将取决于该块运行哪个 SM,哪些块之前运行过,以及这些块完成的更新当前在缓存层次结构中的什么位置。

在考虑块中的线程时,讨论没有实际意义,因为块中的线程可以与共享内存通信,其行为由 CUDA 仔细指定。

于 2012-06-29T19:25:39.813 回答