此问题与GLSL memoryBarrierShared() usefulness?相似。
但是我不知道我们什么时候必须使用subgroupMemoryBarrier
和类似的函数,因为subgroupBarrier
既执行又执行了内存屏障。我了解memoryBarrier
函数,因为barrier
函数不会执行内存屏障。所以您必须同时使用:
memoryBarrier(); // memoryBarrierShared, Buffer, Image...
barrier();
但是我不知道什么时候可以使用subgroupMemoryBarrier
,因为subgroupBarrier
已经使用了它。
GL_KHR_shader_subgroup extension
函数subgroupBarrier()强制所有活动调用 在一个 子组必须先执行此功能,然后才能继续执行 执行,以及使用相干执行的任何内存存储的结果 调用之前执行的变量将在将来可见 由其他着色器调用执行的对同一内存的一致访问 在同一子组中。
如果它们没有用,我认为他们没有实现这些功能。所以我想知道我们什么时候需要使用它们?
是因为假设在子组上它们是并行运行的,所以,您只需发出subgroupMemoryBarrier
。但是在这种情况下,什么时候必须使用subgroupBarrier
?
答案 0 :(得分:1)
这里有两种非常不同的行为,MemoryBarrier()
和Barrier()
。它们的名称都有障碍,但实际上它们的作用完全不同。
内存屏障旨在确保在单个执行线程(例如,单个计算工作项)范围内的某些内存相对排序。在允许进行屏障之后的任何访问之前,必须先完成屏障之前的内存访问。在传统的CPU代码中,这对于诸如锁之类的事情很有用-例如在触摸受保护的结构之前,请确保已成功获取该锁并将其写入内存。子组内部的线程彼此之间的执行不会受到影响,因此您可以并行运行而不浪费管道,子组中的一个线程可以从内存屏障之前运行代码,而另一个线程可以从内存屏障之前运行代码。记忆障碍。
完全障碍旨在重新调整整个子组的执行。从屏障之后到所有线程到达屏障之前,子组中的任何线程都无法运行任何代码,这暗含意味着它们还提供了内存屏障语义。当您想要依靠一个线程需要对子组中的另一个线程到达的位置进行假设的无锁算法时,这就是您需要的。例如,等待localInvocation 0的线程填充本地内存。