gpt4 book ai didi

c++ - 跨多个 gpu 同步原子计数器

转载 作者:行者123 更新时间:2023-11-30 03:57:24 24 4
gpt4 key购买 nike

我在计算着色器中使用原子计数器,其中 atomic_uint 绑定(bind)到动态 GL_ATOMIC_COUNTER_BUFFER(与此 opengl-atomic-counter tutorial lighthouse3d 的方式类似)。

我在粒子系统中使用原子计数器来检查所有粒子是否都达到了条件;当所有粒子都在正确的位置时,我希望看到 counter==numParticles

我每帧映射缓冲区并检查原子计数器是否计算了所有粒子:

GLuint *ptr = (GLuint *) glMapBuffer( GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY );
GLuint particleCount = ptr[ 0 ];
glUnmapBuffer( GL_ATOMIC_COUNTER_BUFFER );
if( particleCount == numParticles() ){ // do stuff }

在单 GPU 主机上,代码运行良好,particleCount 总是达到 numParticles() 但在多 GPU 主机上,particleCount 永远不会达到numParticles()

我可以直观地检查是否已达到条件并且测试应该为真,但是 particleCount 正在改变每一帧的上下变化但从未达到 numParticles()。

在取消映射 particleCount 之前,我在 GL_ATOMIC_COUNTER_BARRIER_BIT 上尝试了一个 opengl 内存屏障:

glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
GLuint *ptr = (GLuint *) glMapBuffer( GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY );
GLuint particleCount = ptr[ 0 ];
glUnmapBuffer( GL_ATOMIC_COUNTER_BUFFER );
if( particleCount == m_particleSystem->numParticles() )
{ // do stuff }

在计算着色器中增加计数器之前,我尝试了 glsl 屏障:

memoryBarrierAtomicCounter();
atomicCounterIncrement( particleCount );

但原子计数器似乎无法跨设备同步。

使原子计数器与多个设备一起工作的正确同步方法是什么?

最佳答案

在这种情况下,您选择的内存屏障实际上是​​不合适的。

该屏障 (GL_ATOMIC_COUNTER_BARRIER_BIT) 将对原子计数器进行更改可见(例如以特定顺序刷新缓存和运行着色器),但它不做的是确保在映射、读取和取消映射缓冲区之前所有并发着色器都已完成。

由于您的缓冲区正在被映射和读回,因此您不需要该屏障 - 该屏障用于着色器 channel 之间的一致性。您真正需要的是确保在您尝试使用 GL 命令读取数据之前完成所有访问原子计数器的着色器,为此您需要 GL_BUFFER_UPDATE_BARRIER_BIT

  • GL_BUFFER_UPDATE_BARRIER_BIT:

Reads/writes via glBuffer(Sub)Data, glCopyBufferSubData, glProgramBufferParametersNV, and glGetBufferSubData, or to buffer object memory mapped by glMapBuffer(Range) after the barrier will reflect data written by shaders prior to the barrier.

Additionally, writes via these commands issued after the barrier will wait on the completion of any shader writes to the same memory initiated prior to the barrier.


您可能从错误的角度思考障碍。您需要的屏障取决于内存读取需要与哪种类型的操作保持一致。

我建议复习一下不连贯的内存访问 usecases :

(1)   Shader write/read between rendering commands

One Rendering Command writes incoherently, and the other reads. There is no need for coherent(GLSL qualifier)​ here at all. Just use glMemoryBarrier​ before issuing the reading rendering command, using the appropriate access bit.

(2) Shader 写入,其他 OpenGL 操作读取

Again, coherent​ is not necessary. You must use a glMemoryBarrier​ before performing the read, using a bitfield that is appropriate to the reading operation of interest.

如果是(1),您想要的屏障实际上是​​ GL_ATOMIC_COUNTER_BARRIER_BIT,因为它将在共享同一个原子计数器。

如果是(2),您需要的屏障是GL_BUFFER_UPDATE_BARRIER_BIT“感兴趣的读取操作”glMapBuffer (...),如上所示,它包含在 GL_BUFFER_UPDATE_BARRIER_BIT 中。

在您的情况下,您正在使用 GL API 读回缓冲区。您需要 GL 命令来等待所有挂起的着色器完成写入(对于不连贯的内存访问,这不会自动发生——图像加载/存储、原子计数器等)。 那是教科书案例(2)

关于c++ - 跨多个 gpu 同步原子计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28024423/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com