问题标签 [gpu-atomics]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
612 浏览

opengl - SSBO 中的 OpenGL 原子计数器与原子计数器

我看到这篇文章指出原子计数器缓冲区和 SSBO 中的原子变量之间的性能没有差异:

https://software.intel.com/en-us/articles/opengl-performance-tips-atomic-counter-buffers-versus-shader-storage-buffer-objects

现在在 nvidia 和 AMD GPU 上真的是这样吗?我想我记得 Radeon 5870 代 GPU 对原子计数器子集具有特定更快的支持吗?所以我认为它在某个时候可能是 AMD 特有的东西?

根据对 nvidia CUDA 的了解,我怀疑这对他们没有任何影响?

有谁知道 AMD/NVidia 原子计数器的哪一代 GPU 不值得购买?

0 投票
1 回答
1570 浏览

cuda - CUDA 中的原子操作是否保证按 Warp 进行调度?

假设我有 8 个块,每块 32 个线程,每个块在 GTX 970 上运行。每个块将全 1 或全 0 写入全局内存中长度为 32 的数组,其中块中的线程 0 写入数组中的位置 0。

现在使用 atomicExch 写入实际值,将数组中的当前值与块尝试写入的值交换。由于 SIMD、原子操作以及 warp 在锁步中执行的事实,我希望数组在任何时间点都只包含 1 或 0。但永远不要将两者混合。

然而,在运行这样的代码时,有几种情况,在某个时间点,数组包含 0 和 1 的混合。这似乎表明原子操作不是每个扭曲都执行的,而是使用其他一些方案进行调度的。

从其他来源我还没有真正找到详细说明跨不同经线的原子操作调度的结论性文章(如果我错了,请纠正我),所以我想知道是否有关于这个主题的任何信息。由于我需要将许多由几个 32 位整数组成的小向量原子地写入全局内存,因此保证原子地写入单个向量的原子操作显然非常重要。

对于那些想知道的人,我编写的代码是在 GTX 970 上执行的,使用 CUDA 8.0 在计算能力 5.2 上编译。

0 投票
0 回答
3052 浏览

opengl - 如何在计算着色器中对 SSBO 使用原子操作

示例代码

这是一个简单的计算着色器来说明我的问题

解释

SMyBuffer是一组元素 ( data[]),其中 acount为当前元素数。当满足某个条件时,计算着色器会自动增加计数。此操作返回用于索引data[]存储新元素的先前索引。这保证了没有两个着色器调用会覆盖彼此的元素。

另一个计算着色器最终会从该堆栈中弹出值并使用它们。glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT)在两个计算着色器调度之间当然需要。

问题

所有这一切都很好,但我想知道我是否只是对时间感到幸运,我想验证我对 API 的使用。

那么,是否需要其他任何东西来确保存储在 SSBO 中的计数器正常工作(参见1)?我期待atomicAdd()处理内存同步,否则它没有什么意义。其效果仅在单个线程中可见的原子操作有什么意义?

关于内存屏障,OpenGL wiki 指出

请注意,原子计数器在功能上与原子图像/缓冲区变量操作不同。后者仍然需要连贯的限定词、障碍等。

这让我想知道是否有一些我没有正确理解的东西并且 amemoryBarrierBuffer()实际上是必需的。atomicAdd()但是,如果是这样的话,在其中一个线程进入下一个线程之前,如何阻止 2 个线程执行memoryBarrierBuffer()

glDispatchCompute()此外,无论派遣一个工作组还是更多,答案是否会改变?

0 投票
3 回答
579 浏览

cuda - CUDA shared-mem atomics-warp locality or anti-locality哪个更快?

假设(CUDA 内核网格)块中的许多扭曲正在重复更新相当数量的共享内存位置。

哪些情况下这样的工作会更快完成?:

  1. 内部warp访问局部性的情况,例如每个warp访问的内存位置总数很少,其中大部分确实是由多个通道访问的
  2. 访问反局部性的情况,所有车道通常都访问不同的位置(并且可能是为了避免银行冲突)?

同样重要的是——这种微架构是依赖于微架构的,还是在所有最近的 NVIDIA 微架构上都基本相同?

0 投票
1 回答
275 浏览

compilation - CUDA 临界区、线程/warp 执行模型和 NVCC 编译器决策

最近我发布了这个问题,关于一个关键部分。这是一个类似的问题。在这些问题中,给出的答案说,代码是否“有效”取决于编译器,因为各种执行路径的顺序取决于编译器

为了详细说明问题的其余部分,我需要从CUDA 编程指南中摘录以下内容:

  1. ...组成warp的各个线程一起从同一个程序地址开始,但它们有自己的指令地址计数器和寄存器状态,因此可以自由地分支和独立执行......
  2. 一个 warp 一次执行一条公共指令,因此当一个 warp 的所有 32 个线程都同意它们的执行路径时,就可以实现完全的效率。如果 warp 的线程通过依赖于数据的条件分支发散,则 warp 会串行执行所采用的每个分支路径,禁用不在该路径上的线程,当所有路径完成时,线程会收敛回相同的执行路径...... .
  3. 多处理器处理的每个 warp 的执行上下文(程序计数器、寄存器等)在 warp 的整个生命周期内都在芯片上维护。因此,从一个执行上下文切换到另一个执行上下文是没有成本的,并且在每个指令发出时间,warp 调度程序都会选择一个线程准备好执行其下一条指令(warp 的活动线程)并将指令发布给这些线程.

我从这三个摘录中了解到,线程可以与其他线程自由分歧,如果线程之间存在分歧,所有分支的可能性都将被序列化,如果采用分支,它将执行直到完成。这就是为什么上面提到的问题以死锁结束的原因,因为编译器强加的执行路径的顺序导致采用没有获得锁的分支。

现在的问题是:编译器不应该总是按照用户编写的顺序放置分支?有没有一种高级方法来强制执行顺序?我知道,编译器可以优化,对指令进行重新排序等,但它不应该从根本上改变代码的逻辑(是的,有一些例外,比如没有 volatile 关键字的内存访问,但这就是关键字存在的原因,将控制权交给用户)。


编辑

这个问题的重点不是关于关键部分,而是关于编译器,例如在第一个链接中,编译标志彻底改变了代码的逻辑。一个“工作”,另一个没有。困扰我的是,在所有参考资料中,它只说要小心,没有关于 nvcc 编译器的未定义行为。

0 投票
1 回答
205 浏览

cuda - 跨并发内核执行的 CUDA 全局原子操作

我的 CUDA 应用程序对卷执行关联缩减。本质上,每个线程都会计算以原子方式添加到全局内存中同一输出缓冲区的重叠位置的值。

是否可以使用不同的输入参数和相同的输出缓冲区同时启动这个内核?换句话说,每个内核将共享相同的全局缓冲区并以原子方式写入它。

所有内核都在同一个 GPU 上运行。

0 投票
1 回答
689 浏览

opencl - 为什么浮点的 OpenCL atomic_add 实现会产生不确定的结果?

我需要float在 OpenCL 的多个线程中添加一个相同的全局内存地址。对于任何两次模拟运行,结果永远不会相同,对atomic_add_f函数的调用是此错误的根源。我正在使用带有驱动程序 436.02 的 Nvidia Titan Xp GPU。

由于 OpenCL 不支持atomic_addwith float,因此可以使用以下方法atomic_cmpxchg

但是,此代码确实会产生不确定的结果。每次运行的结果略有不同,类似于出现竞态条件的情况。

我也试过这个版本

这也不能正常工作。这里提供的版本也不起作用。

这怎么可能以及如何解决?

0 投票
1 回答
152 浏览

concurrency - 关于在cuda中修改标志数组的问题

我正在研究 GPU 编程,并且有一个关于在线程中修改全局数组的问题。

内核应该在预期保持 [1,1,1,1,1,1,1,1,1,1] 的情况下完成执行data,但它陷入了无限循环。为什么会这样?

0 投票
1 回答
72 浏览

optimization - 在CUDA编程中,计算中间结果后,原子函数是否比归约更快?

原子函数(例如atomic_add)在 CUDA 编程中广泛用于计数或执行求和/聚合。但是,与普通全局内存读/写相比,我找不到有关原子函数速度的信息。

考虑以下任务,我们要计算一个具有 256K 元素的浮点数组。每个元素是首先计算的 1000 个中间变量的总和。一种方法是使用atomic_add; 而另一种方法是使用 256K*1000 临时数组作为中间结果,然后减少该数组(通过求和)。

使用原子函数的第一种方法比第二种方法快吗?

0 投票
1 回答
192 浏览

opencl - 64 位原子操作可以在 AMD 卡上的 openCL 中工作吗?

在STREAM 博客之后的 openCL 中模拟原子的实现非常适用于 32 位、CPU 以及 NVIDIA 和 AMD GPU 上的原子添加。

基于cl_khr_int64_base_atomics扩展的 64 位等效项似乎可以在(pocl 和 intel)CPU 以及 NVIDIA openCL 驱动程序上正常运行。

不过,我无法在 AMD GPU 卡上运行 64 位 - 在 amdgpu-pro 和 rocm (3.5.0) 环境中,分别在 Radeon VII 和 Radeon Instinct MI50 上运行。

实现如下:

在不支持双精度类型的原子操作的情况下,想法是利用转换为只要值只需要存储(不需要算术)。然后应该能够按照khronos 手册中long atom_cmpxchg(__global long *p, long cmp, long val)定义的int64 base atomics 使用。

我收到的两种 AMD 环境的错误都指向回退到 32 位版本,编译器似乎无法识别 64 位版本,尽管#pragma

不过,我确实在扩展列表上找到了cl_khr_int64_base_atomics对这两种环境的支持。opencl 驱动程序二进制文件中也存在。clinfocl_khr_int64_base

有人知道这里可能出了什么问题吗?对 32 位使用相同的实现(int 和 float 而不是 long 和 double)对我来说完美无缺......

感谢您的任何提示。