cuda - 何时以及为何在 CUDA 中使用atomicInc()?

标签 cuda atomic

我一直在阅读 CUDA 中的原子操作,并且 atomicInc() 的更新模式似乎相当任意。

来自CUDA Programming Guide :

unsigned int atomicInc(unsigned int* address, unsigned int val);

reads the 32-bit word old located at the address address in global or shared memory, computes ((old >= val) ? 0 : (old+1)), and stores the result back to memory at the same address. These three operations are performed in one atomic transaction. The function returns old.

这是一个增量和“环绕”操作。 atomicInc(&x, val) 非常类似于 x = (x+1) % (val+1)

这对于什么类型的应用程序有用?这是 CUDA 编程中常见的代码模式吗?如果是这样,是否有专用硬件来执行此操作,使 atomicInc() 比使用 atomicCAS() 的等效操作更好?

最佳答案

For what kind of application would this be useful?

如注释中所示,一种可能的应用是异步访问环形缓冲区。具有翻转特性的atomicInc意味着当消费者想要访问环形缓冲区“末尾”之外的元素时,索引(由atomicInc返回)将翻转到开头,即 0。虽然它不是环形缓冲区示例,但涵盖了使用原子进行缓冲区访问的思想 here 。带有atomicInc 的环形缓冲区可能是对其的一个简单扩展。我不会提供有关环形缓冲区的教程。例如,您可能有一个输入索引和一个输出索引,通过两个不同的例程分别维护,这两个例程都使用atomicInc()

Is this a common code pattern in CUDA programming?

根据我的经验,它远不如 atomicAdd 的使用那么常见。

If so, is there dedicated hardware for performing this operation which makes atomicInc() better than an equivalent operation using atomicCAS()?

是的,有专用的(SASS)指令和硬件。单个变量上的任何原子 RMW 操作都可以使用compare-and-swap“模拟” ,但仅限于重试循环。 (如 canonical testing loop 方法中所示。)通常,与专用指令相比,这种方法的效率和性能较低,因为专用指令不需要循环来正确实现。

如果没有这条指令,环形缓冲区的一个选项是使用 1atomicAdd 让计数器自由运行,并让每个用户在使用它之前进行取模(索引环形缓冲区)。 (这是 CPU 实现通常所做的事情;CPU 通常具有原子添加,但没有自定义包装原子公司。)但这仅适用于 2 的幂次缓冲区大小,因此以类型宽度包装不会引入一个偏移量。因此,只需使用 AND 运算即可高效完成此操作,无需实际除法或乘法逆运算。

另一个选项是 CAS 重试循环,您可以手动对旧值进行包装,然后尝试对新值进行 CAS。这允许索引非 2 的幂缓冲区,但效率很低。

atomicInc(大约?)与 atomicAdd 一样快,两者均受硬件支持。在 2 的幂情况下使用它的效率稍高(避免在 atomicAdd 结果上使用 & (size-1)),并且避免 CAS 重试循环非 2 的幂情况。

关于cuda - 何时以及为何在 CUDA 中使用atomicInc()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72989403/

相关文章:

java - java 中 native sun.misc.Unsafe 操作的源代码

c++ - 做原子操作(C++)卡住CPU

openmp - OpenMP 中的原子性和关键性有什么区别?

c++ - 在 CUDA 内核中调用内核

opengl - 如何将 OpenGL 纹理转换为 CUDA 纹理?

c++ - 在 cuda-gdb 中数组值更改时设置断点

cuda - 图灵架构中异步引擎计数的澄清

c++ - openCV 2.4.9 与 CUDA 6.5 的编译错误

hash - Redis 中散列上的原子 GETSET

c - fwrite 是原子的吗?