我曾经在与图形编程相关的技术论文中多次看到“不一致”的和“一致”的内存术语。我一直在寻找一个简单明了的解释,但大多数都是类似于这篇this 难度较高的论文。如果能够得到通俗易懂的回答来解释GPU架构中的一致内存实际上是什么,以及如何与其他(可能是非一致)内存类型进行比较,我将不胜感激。tech papers
内存就是内存。但是不同的设备可以访问这个内存。GPU 可以访问内存,CPU 可以访问内存,可能还有其他硬件部件。
如果其他人对内存所做的更改对读取者是可见的,那么特定的设备对内存具有“一致性”访问。现在,您可能认为这是愚蠢的。毕竟,如果内存已经被更改,某人怎么会不可能看到呢?
简而言之,就是缓存。
事实证明,更改内存是昂贵的。因此,我们尽一切可能避免更改内存,除非我们绝对必须。当您从 CPU 向内存中的指针写入单个字节时,CPU 并不会立即将该字节写入内存。或者至少不是写入内存。它将其写入内存的本地副本,称为“缓存”。
这样做的原因是,一般来说,应用程序不会写入(或读取)单个字节。它们更有可能以小块的方式写入(和读取)大量字节。因此,如果您要执行像内存加载或存储这样的代价高昂的操作,您应该加载或存储大块的内存。因此,您将要对一块内存所做的所有更改存储在缓存中,然后在将来某个时间点上将该缓存块的所有更改作为单个写操作写入实际内存。
但是,如果您有两个不同的设备使用相同的内存,您需要一些方法确保一个设备所做的写入对其他设备是可见的。大多数 GPU 无法读取 CPU 缓存。而且大多数 CPU 语言没有语言级别的支持来表示“嘿,我写入到内存的那些内容?我真正意思是让你现在把它写入内存。” 因此,您通常需要一些东西来确保更改的可见性。
在 Vulkan 中,被标记为 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT 的内存意味着,如果你读/写该内存(通过映射指针,因为这是 Vulkan 允许你直接写入内存的唯一方式),你不需要使用 vkInvalidateMappedMemoryRanges/vkFlushMappedMemoryRanges 函数来确保 CPU/GPU 可以看到这些更改。任何更改的可见性都是双向保证的。如果该标志不可用于内存,则必须使用上述函数来确保你想要访问的特定数据区域的协同性。