独立GPU的内存类型(翻译)

下班买菜

转自:https://mp.weixin.qq.com/s/b77nUf9SfykjqdPGDG1Pyw

本文翻译已征得原作者的同意。

这是原始文章的非官方翻译。

版权由原作者Daniel Rakos保留。

This article has been translated with the permission of the original author.

This is an unofficial translation of the original article.

Copyright is reserved by the original author, Daniel Rakos.

原文地址:

https://www.rastergrid.com/blog/gpu-tech/2020/11/memory-types-of-discrete-gpus/

         

随着最近AMD 显存智取技术的宣布,似乎是写关于针对专用GPU的应用程序可使用的不同类型的内存的正确时机。本文旨在介绍这种系统中的不同内存池,它们的访问特性,以及为什么通过PCI-Express总线实现对整个VRAM的访问可能是一个游戏规则的改变。

         

带宽  

独立GPU的特点是拥有自己的专用内存,即VRAM。内存本身及其与图形板上的GPU的连接都经过优化,以获得最大的带宽,从而能够以足够的速度为许多GPU核心提供数据。这就是为什么独立GPU与集成GPU相比通常具有明显的性能,或者说,这种额外的带宽使它们能够扩展到更高的核心数量。与CPU相比,这是一个根本性的区别,在CPU中,一般是相对较少的核心会访问内存,因此较低的延迟比纯带宽优先级更高。

    不同类型的CPU和GPU存储器的带宽和总线宽度

         

                

上表很好地展示了系统内存和VRAM之间的差异,因为可以看到,GPU使用更宽的总线和带宽优化的内存芯片,提供的有效带宽比系统内存使用的带宽大一个数量级。
尽管如此,系统中的这两个内存池并不是孤立工作的,因为需要有一种方法来相互沟通。这要求至少有一个GPU或CPU能够访问另一个的内存。在实践中,这在两个方向上都是可能的,这让我们看到了下图,描述了这类系统上可用的各种类型的内存。

              

从上面可以看出,GPU可以使用的RAM可以分为两大类。
l本地内存,即VRAM - GPU可以通过其本地宽内存总线访问。
l远程内存,即GPU可见的系统RAM--GPU可通过PCIe总线访问。
从CPU的角度来看,还值得注意的是,有一个CPU可见的VRAM部分,CPU可以通过PCIe总线访问。这就是AMD的显存智取技术发挥作用的地方,我们将在后面看到。
         
我们已经介绍了内存芯片类型本身可能提供的带宽规模,但我们还没有谈到PCI-Express总线带宽,这将是设备间数据共享的限制性因素。
         
GPU通常通过一个PCIe x16连接器连接到主板上。然而,这只是形式因素,因为有效的总线类型(即PCIe版本)和显卡与主板之间可用于通信的PCIe通道数量将是特定CPU、主板、PCIe插槽和GPU所支持数值的共同点。例如,最新的GPU通常支持PCIe 4.0 x16,但它们的低性能版本可能只支持8条通道,许多主板只在其主要的PCIe x16连接器上支持16条通道,第二条(如果有的话)通常被限制为4条通道。

         

不同PCI-Express总线版本和通道数的带宽。

[1] 在每个方向的带宽数据,因为每个通道允许双向通信

[2] 由于128b/130b编码,有效数据率较低

       

看一下上表中的数字就会明白,即使PCIe总线使两个处理器都能访问对方的内存,但可用带宽比各自访问自己的本地内存要低得多,特别是在GPU的情况下。因此,关于某些数据放置位置的决定会对使用该数据的工作负载的性能产生重大影响。

延迟  

到目前为止,我们只谈到了带宽,但是当涉及到向处理器有效提供数据时,另一个重要的因素是访问延迟。不过,在这之前,我们至少应该先谈一谈缓存。
         
我们不会在这里过多地讨论现代CPU和GPU的缓存层次,因为这本身就值得更深入的讨论。尽管如此,值得注意的是,两者都以某种形式存在,以提高空间上的局部内存读取(例如从附近的内存地址读取)和对同一数据的多次访问的性能。需要注意的一个关键是,与CPU相比,GPU遵循更宽松的缓存一致性规则,主要是为了追求更高的性能,这意味着GPU通常会对所有的内存访问进行缓存,而CPU往往不是这样,特别是在访问GPU内存数据时。
         
特别是在远程内存堆的背景下,也就是系统内存中可用作图形内存的部分(即GPU可访问的部分),单个内存分配可以被标记为缓存或未缓存,控制CPU是否被允许缓存底层内存的数据。我们将在本文后面讨论这一区别的一些影响,但现在的关键是,这给我们留下了以下四种图形内存类型
总之,所有的图形内存访问都是由GPU缓存的,但除了远程缓存的内存外,没有一个是由CPU缓存的。这一点很重要,至少要注意以下几个原因。
但让我们首先关注内存访问延迟,暂时忽略缓存。下表列出了从CPU和GPU角度测量的内存读取延迟,分别是在访问不同类型的内存时。由于本地可见内存和不可见内存的访问特性是相同的,因为它们之间唯一的区别是VRAM的相应部分是否对CPU可见,所以表格中显示了一组使用本地可见内存的测量结果。

Ryzen 5 3600X和Radeon RX 580通过PCIe 3.0 x16的不同内存类型的内存读取延迟。

[1] 取决于GPU时钟速率,可能高达1900 ns。

[2] 延迟是在CPU缓存缺失的情况下测量的,在L1/L2/L3缓存命中的情况下,延迟是~1/3/9 ns。

[3] 延迟是在GPU缓存丢失的情况下测量的,在L2缓存命中的情况下,延迟是~ 150 ns

这些数值告诉我们两个故事。首先,它们很好地显示了VRAM比系统内存有更高的延迟,这与我们已经讨论过的关于GPU内存系统即使以增加延迟为代价也要对吞吐量进行优化的情况相一致。第二,从数据中可以看出,通过PCIe总线进行内存访问会大大增加操作的延迟。
         

支持可调整的BAR  

现在我们有了关于不同内存类型及其性能特点的最重要信息,让我们来谈谈可调整大小的BAR支持,这是AMD显存智取技术的核心。
         
要寻址PCIe设备,必须通过将其映射到系统的I/O端口或内存地址空间来启用,这样设备驱动程序就能够与底层硬件进行通信,无论是直接I/O还是发送到设备的内存映射I/O操作,还是访问设备的物理内存,如果有的话。这是通过对基础地址寄存器(或BAR)进行编程来实现的。可用的本地可见内存是由这个BAR配置决定的。
         
传统上,GPU内存BAR的大小被限制在256MB,这意味着无论显卡上有多少VRAM,CPU都只能看到其中256MB的窗口。即使是这个小窗口也并不总是可以供应用程序开发人员使用。在像OpenGL这样的传统API的早期,这种访问已经受到了限制,因为API没有为应用程序提供明确选择特定内存类型的方法,而是由图形驱动程序根据应用程序提供的使用意图来选择适当的内存类型。
         
这种情况随着Vulkan等新的API的出现而改变,这些API明确地暴露了各个内存类型,使应用开发者能够完全控制选择内存分配和资源的位置。尽管即使在那里,本地可见内存的可用性在很长一段时间内也没有普及,AMD从一开始就暴露了它,而NVIDIA直到今年早些时候才跟进。
         
不过,直到最近,本地可见内存仍被限制在256MB的窗口内,尽管自2008年以来,可调整大小的BAR是PCIe规范的一部分。但立即采用可能不是一种正确的选择,因为当时32位操作系统仍然很普遍,从这类系统已经很小的4GB地址空间中拿出超过256MB的图形内存是不现实的。也就是说,我们不得不等待这么久才出现这一功能的主要原因可能是在硬件/固件/软件堆栈的某些层面缺乏适当的支持,例如,Windows的支持似乎只是最近才出现。

         

AMD是第一个启用可调整大小的BAR支持的公司,即使目前支持仅限于AMD的最新显卡系列。尽管如此,我们很快就可以预计,对可调整大小的BAR的支持会在所有供应商和支持的产品中激增,因为该技术没有任何根本性的先决条件,事实上,它主要是通过在堆栈的各个部分实现支持来利用现有的能力,不管是BIOS、操作系统还是设备驱动程序。因此,NVIDIA有兴趣推出他们自己的SAM版本,而AMD愿意帮助其竞争对手在其他系统配置上启用该功能,这并不令人惊讶。特别有趣的是,为了加速采用该功能,供应商将(以及能够)在多大程度上进行反向移植。
         
这意味着本地不可见内存的日子已经过去了,我们很快就能看到整个VRAM作为本地可见内存暴露在所有供应商的独立GPU和所有平台上的Vulkan等API中。
         

性能优势  

从带宽和延迟的数字可以看出,将所有可能需要被GPU访问的数据保留在VRAM中,可以提供最好的性能,但如何使CPU访问整个VRAM可以提供媒体上已经证明的性能优势就不那么重要了。为了更好地理解这背后的原因,我们需要承认,应用程序通常在CPU上每帧动态生成大量的输入数据,假设这些数据是每一帧和每一个物体的常量数据(例如变换)、其他动态几何数据、流式资源或任何其他数据。这些都是需要写到内存中的操作,之后可以由GPU访问。
         
这些操作的明显目标选择是本地可见内存分配中的缓冲内存,因为我们并不真正关心写操作的延迟,而且从GPU众多内核后续读取的角度来看,数据将在最有性能的内存中可用。然而,由于传统的256MB本地可见内存窗口很容易被耗尽,一旦发生这种情况,应用程序往往不得不求助于以下退路之一。
(1)使用远程内存代替(通常是远程未缓存)。
(2)先写到远程内存,然后使用GPU拷贝上传到本地不可见内存
与能够直接写入本地可见内存相比,这两种方法都有其缺点,因为(1)会导致GPU收到每次请求都要经过PCIe总线的带宽和延迟惩罚的限制,而(2)需要额外的复制,即使使用GPU的内置DMA引擎执行,从而不占用任何GPU核心处理时间,也需要时间来完成,并且可能需要额外的同步操作,更不用说它至少暂时使整个内存需求增加一倍。
          

使用本地可见内存与可用的退路选项的说明。

实际的相对性能取决于数据大小、工作负载类型、可用的独立工作和其他不属于本讨论范围的因素。

对于许多GPU工作项目(线程)共享的少量数据,如每一帧或每一画的常数,使用方法(1)可能是可以接受的,因为PCIe总线相对较低的带宽不会成为限制因素,而且如果数据足够小,使用频率足够高,它可能会留在GPU上缓存,因此PCIe总线的延迟成本可以在许多读取它的线程中分摊。尽管如此,与从VRAM访问相比,增加的延迟仍然会对性能产生影响,因为在第一次访问时,很可能会有成千上万的线程被阻塞,等待数据的到来,而没有或没有足够的独立工作准备好让GPU隐藏这个延迟,而且根据内存访问模式,数据也可能在处理帧或绘图调用的过程中被多次从GPU的缓存中驱逐。
         
对于较大的数据集,无论它们是流式读取还是 "随机 "访问,方法(2)比(1)更可取,因为除了延迟惩罚之外,由于PCIe总线的带宽有限,GPU也更有可能努力为其处理核心提供足够快的数据。即使从远程到本地内存的DMA传输也受到PCIe连接带宽的限制,但与GPU响应线程内读取的更不规则的读取突发相比,它可能会更好地利用可用的带宽,更不用说在此期间,依赖线程不会占用GPU内核上宝贵的寄存器空间,允许更多的非依赖工作执行。
         
这些就是为什么由于可调整大小的BAR支持,让CPU访问整个VRAM会对整体性能产生非常直接的影响的主要原因,但到目前为止,我们只谈到了由应用程序直接分配的图形内存,而图形驱动本身也有自己的资源需要存储在GPU可访问的内存中。这些资源包括用于内部目的的传统资源、描述符表/池(通常由GPU直接从图形内存中获取),以及房间里的大象:命令缓冲区内存。如果驱动程序使用本地可见内存,那么应用程序可供自己使用的内存就会减少,如果256MB的窗口被耗尽,驱动程序就必须使用与应用程序类似的退路方法。因此,上述的原则也适用于这些驱动内部的资源。

例外情况  

我们已经看到,一般来说,本地内存是存储GPU数据的最佳位置。不过,这并不意味着所有的数据都可以而且应该存储在本地内存中。对于非常大的数据集来说,根本不可能把所有的东西都放在VRAM中,因此往往需要使用远程内存作为备份存储,或者更好的是,VRAM应该被用作活动(或最关键的性能)数据集的缓存。此外,在一些特定情况下,远程内存是存储某些数据的更好选择。
         
一个例子是用于纹理上传的暂存缓冲区。由于纹理数据通常在应用方面是以独立于设备的格式提供的,无论如何都需要转换为目标GPU支持的最佳平铺格式,因此间距线性平铺纹理数据最好由CPU写入远程非缓存内存,然后通过使用显卡的DMA引擎进行所谓的线性到平铺的拷贝上传到VRAM。数据无论如何要经过一次PCIe总线,而DMA引擎可能会更有效地执行,同时也不会消耗任何CPU或GPU的处理核心时间。
         
另外,由于本地内存没有被CPU缓存,任何非重要的数据回读,比如纹理或缓冲区数据,都可以从使用远程缓存的内存中受益,因为在回读过程中利用CPU缓存可以快几个数量级。不过,"非重要 "的部分很重要,因为对于回读小块数据,比如一个计数器值或一个查询结果,使用未缓存的内存仍然是首选,因为它通常可以消除使CPU缓存失效的需要。

总结  

我们设法涵盖了与带有独立GPU的系统上可用的内存类型有关的关键主题。我们已经看到了CPU和GPU是否以及如何访问这些内存类型中的数据,以及这些访问的带宽和延迟特性是什么。
         
本文的新闻焦点是最近AMD的显存智取技术的到来以及其引入的影响。该功能本身是一个很好的例子,说明为什么技术世界不应该满足于现状,因为它实现了一个相当简单的功能,具有很大的好处,如果它不会被支持的硬件/固件/软件堆栈中的小差距所阻碍,那么它本来可以更早地出现。
         
作为讨论的一部分,我们还看到了CPU何时以及如何访问整个VRAM来提高整个应用程序的性能,并且总体上涵盖了不同类型图形存储器的主要使用情况。
         
虽然可调整大小的BAR支持不是独立GPU技术的圣杯,但它对应用开发者来说绝对是一个游戏规则的改变,他们现在有更大的自由度将他们的数据放在适当的内存池中,同时消除了以前可能需要的不必要的拷贝来实现这一目的。