什么是GPU上的连贯内存



在中,我从未遇到过"非相干"one_answers"相干"记忆这两个术语

与图形编程相关的技术论文。我一直在寻找一个简单明了的解释,但发现的大多是这类"铁杆"论文。我很高兴收到外行风格的答案,关于GPU架构上的相干内存到底是什么,以及它与其他(可能不是相干的)内存类型的比较。

内存就是内存。但不同的东西可以访问这种记忆。GPU可以访问内存,CPU可以访问内存、也许其他硬件位,等等。

一个特定的事物具有";连贯的";如果其他人对内存所做的更改对读取器可见,则访问内存。现在,你可能会认为这是愚蠢的。毕竟,如果记忆被改变了,怎么会有人看不见呢?

简单地说,缓存。

事实证明,改变内存是很昂贵的。因此,我们尽一切可能避免更改内存,除非万不得已。当你从CPU向内存中的指针写入一个字节时,CPU还没有写入该字节。或者至少,不是为了记忆。它将其写入该存储器的本地副本,称为";缓存"

原因是,一般来说,应用程序不写入(或读取)单个字节。他们更有可能以小块的形式写入(和读取)大量字节。因此,如果你要执行一个昂贵的操作,比如内存加载或存储,你应该加载或存储一大块内存。因此,您将要对内存块进行的所有更改存储在缓存中,然后在未来的某个时候将缓存的内存块写入实际内存。

但是,如果你有两个使用相同内存的独立设备,你需要某种方式来确保一个设备所做的写入对其他设备可见。大多数GPU无法读取CPU缓存。并且大多数CPU语言不具有语言级别的支持;嘿,我写的那些东西是为了纪念吗?我真的想让你现在就把它写下来"因此,您通常需要一些东西来确保更改的可见性。

在Vulkan中,用VK_MEMORY_PROPERTY_HOST_COHERENT_BIT标记的内存意味着,如果您读取/写入该内存(通过映射指针,因为这是Vulkan允许您直接写入内存的唯一方式),则不需要使用函数vkInvalidateMappedMemoryRanges/vkFlushMappedMemoryRanges来确保CPU/GPU能够看到这些更改。任何更改在两个方向上的可见性都得到了保证。如果该标志在内存中不可用,则必须使用上述函数来确保要访问的特定数据区域的一致性。

对于相干内存,硬件方面有两件事。CPU对内存的访问没有缓存在CPU的任何缓存中,或者GPU可以直接访问CPU的缓存(可能是因为与CPU在同一个芯片上)。你通常可以看出后者正在发生,因为Vulkan的片上GPU实现不需要提供非相干内存选项。

如果内存是一致的,那么访问该内存的所有线程必须始终就内存的状态达成一致,例如:如果线程0读取内存位置A,线程1同时读取相同位置,则两个线程应该始终读取相同的值。

但如果内存不一致,那么线程A和B可能会读回不同的值。线程0可能认为位置A包含1,而线程则认为该位置包含2。不同的线程对内存的看法会不连贯。

使用大量内核很难实现一致性。通常,每个核心都必须知道来自所有其他核心的内存访问。因此,如果四核CPU中有4个核,那么一致性就不难实现,因为每个核都必须被告知其他3个核的内存访问地址,但在有16个核的GPU中,每个核必须知道其他15个核的存储器访问。核心使用所谓的"缓存一致性协议"交换有关其缓存内容的数据。

这就是为什么GPU通常只支持有限形式的一致性。如果某些内存位置是只读的或仅由单个线程访问,则不需要一致性。如果缓存很小,并且并不总是需要一致性,而是只需要程序的特定指令,那么可以在特定内存访问之前或之后使用缓存刷新来实现程序的正确行为。

如果你的硬件同时提供相干和非相干内存类型,那么你可以预期非相干内存会更快,但如果你试图使用这种内存运行并行算法,它们会以非常奇怪的方式失败。

相关内容

  • 没有找到相关文章

最新更新