这是 Vulkan 语义(如果有什么不同的话)。
假设如下:
layout(...) coherent buffer B
{
uint field;
} b;
假设该字段正在被同一着色器(或派生着色器)的其他调用修改atomic*()
功能。
如果着色器调用想要从中执行原子读取field
(具有相同的语义atomicCounter()
在 GLES 中,如果这是atomic_uint
相反),以下两者之间有什么区别(除了显然其中一个既可以写也可以读)?
uint read_value = b.field;
uint read_value2 = atomicAdd(b.field, 0);
为了直接回答这个问题,这两行代码生成不同的指令,具有不同的性能特征和硬件管道使用情况。
uint read_value = b.field; // generates a load instruction
uint read_value2 = atomicAdd(b.field, 0); // generates an atomic instruction
-
AMD拆解可以看这个在线Shader Playground http://shader-playground.timjones.io/0733f88ba4b8ddd197c0242b1273044d --
buffer_load_dword
versus buffer_atomic_add
-
通过微基准测试剖析 NVIDIA Volta GPU 架构 https://arxiv.org/abs/1804.06826 --
LDG
versus ATOM
The GLSL规格 https://www.khronos.org/registry/OpenGL/specs/gl/GLSLangSpec.4.40.pdf第 4.10 节内存限定符指出coherent
仅涉及跨调用(着色器线程)的读取和写入的可见性。他们还对隐含的性能发表了评论:
当使用未声明为一致的变量访问内存时,着色器访问的内存可能会被实现缓存,以服务将来对同一地址的访问。内存存储可以以这样的方式进行缓存:写入的值对于访问同一内存的其他着色器调用可能不可见。该实现可以缓存由内存读取获取的值,并将相同的值返回到访问同一内存的任何着色器调用,即使自第一次内存读取以来底层内存已被修改。虽然未声明为一致的变量可能对着色器调用之间的通信没有用处,但使用非一致访问可能会带来更高的性能。
GPU 内存系统中的一致性点通常是最后一级缓存(L2 缓存),这意味着所有一致性访问都必须由 L2 缓存执行。这也意味着相干缓冲区无法缓存在 L1 或更靠近着色器处理器的其他缓存中。现代 GPU 还在 L2 缓存中配备了专用的原子硬件;普通负载不会使用这些,但是atomicAdd(..., 0)
会经历那些。原子硬件的带宽通常比完整的二级缓存低。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)