我们是否可以保证,当内核执行结束时,这些写入之一的结果将出现在该位置,而不是一些垃圾?
对于当前的 CUDA GPU,我非常确定对于采用 OpenCL 的 NVIDIA GPU,答案是肯定的。我下面的大部分术语都会考虑到 CUDA。如果您需要 CUDA 和 OpenCL 的详尽答案,请告诉我,我将删除此答案。与此非常相似的问题 https://stackoverflow.com/questions/22151070/cuda-non-atomic-write-clash-results/22151276#22151276无论如何,之前已经被问过并回答过。这是另一个 https://stackoverflow.com/questions/20775033/are-general-reads-and-writes-to-global-memory-atomic-in-cuda-if/20775278#20775278,而且我确信还有其他人。
当同一位置发生多个“同时”写入时,其中一个将完好无损地获胜。
哪一方会获胜尚无定论。非获胜写入的行为也是未定义的(它们可能发生,但被获胜者取代,或者它们可能根本不发生。)内存位置的实际内容可能会通过各种值(例如原始值)进行转换,加上任何有效的写入值),但传输不会传递“垃圾”值(即不存在且未由任何线程写入的值。)传输最终以“获胜者”结束。
示例1:
位置 X 包含零。线程 1、5、32、30000 和 450000 都向该位置写入 1。如果该位置没有其他写入流量,则该位置最终将包含值 1(在内核终止时或更早)。
示例2:
位置 X 包含 5。线程 32 将 1 写入 X。线程 90303 将 7 写入 X。线程 432322 将 972 写入 X。如果没有其他写入流量到该位置,则在内核终止时或更早,位置 X 将包含 1 、7 或 972。它不会包含任何其他值,包括 5。
我假设 X 位于全局内存中,并且到它的所有流量自然地与它对齐,并且到它的所有流量具有相同的大小,尽管这些原则也适用于共享内存。我还假设您没有违反 CUDA 编程原则,例如自然排列的交通 http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#device-memory-accesses到设备内存位置。我在这里看到的事务是源自单个 SASS 指令(每个线程)的事务。此类事务的宽度可以为 1、2、4 或 8 字节。无论写入是源自“同一行代码”还是“不同行”,我在这里所做的声明都适用。
这些声明基于 PTX 内存一致性模型,因此“正确性”是由 GPU 硬件保证的,而不是由编译器、CUDA 编程模型或 CUDA 所基于的 C++ 标准来保证。
这是一个相当复杂的主题(特别是当我们考虑缓存行为,以及当我们将读取混合在一起时会发生什么),但是“垃圾”值应该never发生。全局内存中应该出现的唯一值是那些一开始就存在的值,或者是由某个线程在某处写入的那些值。