什么是GPU上的连贯内存?

时间:2016-03-26 21:17:43

标签: gpu gpgpu gpu-programming vulkan

我在

中偶然发现了一段“非连贯”和“连贯”的记忆。

tech papers与图形编程相关。我一直在寻找一个简单明了的解释,但发现了大多数this类型的“硬核”论文。我很乐意接受外行人的风格回答相干内存实际上是在GPU架构上,以及如何与其他(可能不相干)内存类型进行比较。

2 个答案:

答案 0 :(得分:25)

记忆是记忆。但是不同的东西可以访问那个记忆。 GPU可以访问内存,CPU可以访问内存,也可以访问其他硬件位。

特别的事情是"连贯的"如果其他人对该内存所做的更改可见,则可以访问内存。现在,你可能会认为这是愚蠢的。毕竟,如果内存已被更改,那么可能的人怎么可能无法看到它呢?

简单地说,缓存。

事实证明,改变内存是昂贵的。所以我们尽一切可能避免改变内存,除非我们绝对必须这样做。当您将CPU中的单个字节写入内存中的指针时,CPU尚未写入该字节。或者至少,不是记忆。它将其写入该内存的本地副本,称为"缓存。"

原因在于,一般来说,应用程序不会写入(或读取)单个字节。它们更有可能以小块的形式写入(并读取)大量字节。因此,如果您要执行像内存加载或存储这样的昂贵操作,则应加载或存储大量内存。因此,您将要进行的所有更改存储到缓存中的一块内存中,然后在将来的某个时刻将该缓存的块写入实际内存。

但是如果你有两个使用相同内存的独立设备,你需要一些方法来确保写入一个设备使其他设备可见。大多数GPU无法读取CPU缓存。大多数CPU语言都没有语言级别的支持来说“嘿,那些我写入内存的东西?”我真的很想让你现在把它写到记忆中。"所以你通常需要一些东西来确保变化的可见性。

在Vulkan中,标记为" HOST_COHERENT"意味着,如果你写入该内存(通过映射指针,因为这是Vulkan允许你直接写入内存的唯一方法),你需要使用特殊内存确保GPU可以看到这些更改的功能。 GPU保证了任何变化的可见性。如果该标志在内存中不可用,则必须使用Vulkan API来确保您要访问的特定数据区域的一致性。

对于连贯的内存,硬件方面正在进行两件事之一。 CPU访问内存不会缓存在任何CPU的缓存中,或者GPU可以直接访问CPU的缓存(可能是由于与CPU处于相同的芯片上) 。你通常可以告诉后者正在发生,因为Vulkan的片上GPU实现并不打算提供非连贯的内存选项。

答案 1 :(得分:6)

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

但是如果内存不连贯,那么线程A和B可能会读回不同的值。线程0可以认为位置A包含1,而线程认为该位置包含2.不同的线程将具有内存的不连贯视图。

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

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

如果您的硬件提供相干和非连贯的内存类型,那么您可以预期非连贯内存会更快,但如果您尝试使用此内存运行并行算法,它们将以非常奇怪的方式失败。