转载:
计算机缓存Cache以及Cache Line详解 - 围城的文章 - 知乎 https://zhuanlan.zhihu.com/p/37749443
L1,L2,L3 Cache究竟在哪里? - 老狼的文章 - 知乎 https://zhuanlan.zhihu.com/p/31422201
Cache是怎么组织和工作的? - 老狼的文章 - 知乎 https://zhuanlan.zhihu.com/p/31859105
Cache为什么有那么多级?为什么一级比一级大?是不是Cache越大越好? - 老狼的文章 - 知乎 https://zhuanlan.zhihu.com/p/32058808
显存为什么不能当内存使?内存、Cache和Cache一致性 - 老狼的文章 - 知乎 https://zhuanlan.zhihu.com/p/63494668
1.计算机存储体系简介
存储器是分层次的,离CPU越近的存储器,速度越快,每字节的成本越高,同时容量也因此越小。寄存器速度最快,离CPU最近,成本最高,所以个数容量有限,其次是高速缓存(缓存也是分级,有L1,L2等缓存),再次是主存(普通内存),再次是本地磁盘。
寄存器的速度最快,可以在一个时钟周期内访问,其次是高速缓存,可以在几个时钟周期内访问,普通内存可以在几十个或几百个时钟周期内访问。
存储器分级,利用的是局部性原理。我们可以以经典的阅读书籍为例。我在读的书,捧在手里(寄存器),我最近频繁阅读的书,放在书桌上(缓存),随时取来读。当然书桌上只能放有限几本书。我更多的书在书架上(内存)。如果书架上没有的书,就去图书馆(磁盘)。我要读的书如果手里没有,那么去书桌上找,如果书桌上没有,去书架上找,如果书架上没有去图书馆去找。可以对应寄存器没有,则从缓存中取,缓存中没有,则从内存中取到缓存,如果内存中没有,则先从磁盘读入内存,再读入缓存,再读入寄存器。
2.计算机缓存 Cache
本系列的文章重点介绍缓存cache。了解如何获取cache的参数,了解缓存的组织结构。
2.1 Cache 概述
cache,中译名高速缓冲存储器,其作用是为了更好的利用局部性原理,减少CPU访问主存的次数。简单地说,CPU正在访问的指令和数据,其可能会被以后多次访问到,或者是该指令和数据附近的内存区域,也可能会被多次访问。因此,第一次访问这一块区域时,将其复制到cache中,以后访问该区域的指令或者数据时,就不用再从主存中取出。
cache分成多个组,每个组分成多个行,linesize是cache的基本单位,从主存向cache迁移数据都是按照linesize为单位替换的。比如linesize为32Byte,那么迁移必须一次迁移32Byte到cache。 这个linesize比较容易理解,想想我们前面书的例子,我们从书架往书桌搬书必须以书为单位,肯定不能把书撕了以页为单位。书就是linesize。当然了现实生活中每本书页数不同,但是同个cache的linesize总是相同的。
所谓8路组相连( 8-way set associative)的含义是指,每个组里面有8个行。
我们知道,cache的容量要远远小于主存,主存和cache肯定不是一一对应的,那么主存中的地址和cache的映射关系是怎样的呢?
拿到一个地址,首先是映射到一个组里面去。如何映射?取内存地址的中间几位来映射。
举例来说,data cache: 32-KB, 8-way set associative, 64-byte line size
Cache总大小为32KB,8路组相连(每组有8个line),每个line的大小linesize为64Byte,OK,我们可以很轻易的算出一共有32K/8/64=64 个组。
对于32位的内存地址,每个line有2^6 = 64Byte,所以地址的【0,5】区分line中的那个字节。一共有64个组。我们取内存地址中间6为来hash查找地址属于那个组。即内存地址的【6,11】位来确定属于64组的哪一个组。组确定了之后,【12,31】的内存地址与组中8个line挨个比对,如果【12,31】为与某个line一致,并且这个line为有效,那么缓存命中。
OK,cache分成三类,
1 直接映射高速缓存,这个简单,即每个组只有一个line,选中组之后不需要和组中的每个line比对,因为只有一个line。
2 组相联高速缓存,这个就是我们前面介绍的cache。 S个组,每个组E个line。
3 全相联高速缓存,这个简单,只有一个组,就是全相联。不用hash来确定组,直接挨个比对高位地址,来确定是否命中。可以想见这种方式不适合大的缓存。想想看,如果4M 的大缓存 linesize为32Byte,采用全相联的话,就意味着4*1024*1024/32 = 128K 个line挨个比较,来确定是否命中,这是多要命的事情。高速缓存立马成了低速缓存了。
描述一个cache需要以下参数 :
1 cache分级,L1 cache, L2 cache, L3 cache,级别越低,离cpu越近
2 cache的容量
3 cache的linesize
4 cache 每组的行个数.
2.2 Cache 结构
假设内存容量为M,内存地址为m位:那么寻址范围为000…00~FFF…F(m位)
倘若把内存地址分为以下三个区间:
tag, set index, block offset三个区间有什么用呢?再来看看Cache的逻辑结构吧:
将此图与上图做对比,可以得出各参数如下:
B = 2^b
S = 2^s
现在来解释一下各个参数的意义:
一个cache被分为S个组,每个组有E个cacheline,而一个cacheline中,有B个存储单元,现代处理器中,这个存储单元一般是以字节(通常8个位)为单位的,也是最小的寻址单元。因此,在一个内存地址中,中间的s位决定了该单元被映射到哪一组,而最低的b位决定了该单元在cacheline中的偏移量。valid通常是一位,代表该cacheline是否是有效的(当该cacheline不存在内存映射时,当然是无效的)。tag就是内存地址的高t位,因为可能会有多个内存地址映射到同一个cacheline中,所以该位是用来校验该cacheline是否是CPU要访问的内存单元。
当tag和valid校验成功是,我们称为cache命中,这时只要将cache中的单元取出,放入CPU寄存器中即可。
当tag或valid校验失败的时候,就说明要访问的内存单元(也可能是连续的一些单元,如int占4个字节,double占8个字节)并不在cache中,这时就需要去内存中取了,这就是cache不命中的情况(cache miss)。当不命中的情况发生时,系统就会从内存中取得该单元,将其装入cache中,与此同时也放入CPU寄存器中,等待下一步处理。注意,以下这一点对理解linux cache机制非常重要:
3.计算机缓存行 ChaceLine
高速缓存其实就是一组称之为缓存行(cache line)的固定大小的数据块,其大小是以突发读或者突发写周期的大小为基础的。
每个高速缓存行完全是在一个突发读操作周期中进行填充或者下载的。即使处理器只存取一个字节的存储器,高速缓存控制器也启动整个存取器访问周期并请求整个数据块。缓存行第一个字节的地址总是突发周期尺寸的倍数。缓存行的起始位置总是与突发周期的开头保持一致。
当从内存中取单元到cache中时,会一次取一个cacheline大小的内存区域到cache中,然后存进相应的cacheline中。
例如:我们要取地址 (t, s, b) 内存单元,发生了cache miss,那么系统会取 (t, s, 00…000) 到 (t, s, FF…FFF)的内存单元,将其放入相应的cacheline中。
下面看看cache的映射机制:
当E=1时, 每组只有一个cacheline。那么相隔2^(s+b)个单元的2个内存单元,会被映射到同一个cacheline中。(好好想想为什么?)
当1<E<C/B时,每组有E个cacheline,不同的地址,只要中间s位相同,那么就会被映射到同一组中,同一组中被映射到哪个cacheline中是依赖于替换算法的。
当E=C/B,此时S=1,每个内存单元都能映射到任意的cacheline。带有这样cache的处理器几乎没有,因为这种映射机制需要昂贵复杂的硬件来支持。
不管哪种映射,只要发生了cache miss,那么必定会有一个cacheline大小的内存区域,被取到cache中相应的cacheline。
现代处理器,一般将cache分为2~3级,L1, L2, L3。L1一般为CPU专有,不在多个CPU中共享。L2 cache一般是多个CPU共享的,也可能装在主板上。L1 cache还可能分为instruction cache, data cache. 这样CPU能同时取指令和数据。
4、L1,L2,L3 Cache究竟在哪里?
什么是Cache?
Cache Memory也被称为Cache,是存储器子系统的组成部分,存放着程序经常使用的指令和数据,这就是Cache的传统定义。从广义的角度上看,Cache是快设备为了缓解访问慢设备延时的预留的Buffer,从而可以在掩盖访问延时的同时,尽可能地提高数据传输率。 快和慢是一个相对概念,与微架构(Microarchitecture)中的 L1/L2/L3 Cache相比, DDR内存是一个慢速设备;在磁盘 I/O 系统中,DDR却是快速设备,在磁盘 I/O 系统中,仍在使用DDR内存作为磁介质的Cache。在一个微架构中,除了有L1/L2/L3 Cache之外,用于虚实地址转换的各级TLB, MOB( Memory Ordering Buffers)、在指令流水线中的ROB,Register File和BTB等等也是一种Cache。我们这里的Cache,是狭义 Cache,是CPU流水线和主存储器的 L1/L2/L3 Cache。
Cache在哪里呢?
也许很多人会不假思索的说:“在CPU内核里。”Not so fast!它也有可能在主板上!我们需要了解一下Cache的历史。
Cache速度比内存速度快多少?
大家都知道内存都是DRAM,但对Cache是怎么组成就所知不多了。Cache是由CAM(Content Addressable Memory )为主体的tag和SRAM组成的。
各级Cache的延迟差距很大,如下图:
可以看到延迟最低的是Registers和MOB(Memory Ordering Buffers),L1的延迟和CPU core在一个数量级之内(注意这里并不能简单的认为L1就是3个Cycle,因为有pre-fetch),而DRAM延迟是它的60多倍。
5、Cache是怎么组织和工作的?什么是n-ways Set-Associative Cache?
我们经常能够看到2-ways,4-ways cache,它是什么意思呢?Cache和内存地址是怎么对应起来的呢?今天我们就介绍这个内容。
在CPU中, Cache Memory 处于 Memory Hierarchy 的最顶端,其下是内存和外存。
那么CPU是如何访问Cache的呢?和访问内存类似,CPU微架构也对各级Cache地址空间进行了编码,只是这些编码并不能够被软件所体察。为简化起见,我们忽略各级Cache的区别,仅仅讨论一般意义上Cache的访问。
Cache的组成和访问方式
在现代大多数处理器中,Cache被分为很多行(Cache Line),Cache Line大小不一,从16Byte到128Byte不等,一般大小是64个Byte,我们在这之后都认为Cache Line有64B组成。我们假设有512KB的Cache,就可以划分成8192个Cache Line
那么一个地址访问如何映射到Cache中去呢?我们都知道地址分为逻辑地址(虚拟地址)、线性地址和物理地址。一个虚拟地址变换成物理地址的简单过程如下图,我就不详细说明了:
变换过程中线性地址到物理地址需要用到页表(page table)。页表由很多项组成,每一项叫一个页表项,整个页表由操作系统维护,并放置在内存中(或磁盘中)。从上文(L1,L2,L3 Cache究竟在哪里?)我们知道,一次内存访问需要数百个时钟周期,如果每次地址转换都要查看内存页表也太浪费时间了。现代计算机为了加速这一过程,引入了翻译后援缓冲器TLB。TLB可以看作页表的Cache,CPU每次转换地址都会查看TLB,如果有了就不用去取内存页表了。
那么TLB和Cache有什么关系呢?可以说TLB命中是Cache命中的基本条件。TLB不命中,会更新TLB项,这个代价非常大,Cache命中的好处基本都没有了。在TLB命中的情况下,物理地址才能够被选出,Cache的命中与否才能够达成。如下图:
n-ways Set-Associative Cache
从前文可以看出知道物理地址,那就能够知道Cache命中与否。那么Cache地址和物理地址的对应关系有很多种。我们先看两个极端的例子:
- 直接映射(Direct Mapping)
直接映射可以理解为每个地址都可以立刻直接且只能映射到某个Cache Line上。还是举前面那个512KB Cache的例子。假设我们有1GB物理内存,我们把它们分成8192份,每份就是128KB。则我们的直接映射Cache算法就是每个128KB块里面所有的地址都只能映射到相应的Cache Line中。我们判断Cache命中的算法就很简单,直接地址/128KB,商就是Cache Line的地址,如果里面的确是该地址就命中,否则就不明中,简单高效,运算十分迅速。意义图如下:
图片来自HardwareSecrets
这样做看起来很高效,哪有那些坏处呢?那就是Cache Miss率极高,因为数据的相关性和局限性,同一时刻需要用的数据大部分都在附近,会造成Cache频繁换进换出,造成颠簸。一个改进的做法是用inteleave,但也会造成Cache Miss很大,冷热不均。
- 全相联映射(Fully Associative Mapping)
全映射就是所有Cache Line可以对应说有地址。这样Cache就不会造成冷热不均,Cache Miss减小了很多,但与此同时带来了另外的问题,那就是查找Cache命中与否的代价(Over head)很高。一条不命中的寻找,要遍历整个Cache,才能最终确定下来。
直接映射在Cache刚刚发明时大行其道,但随着Cache的发展,它的问题也被暴露了出来,于此同时全相连也不是很好的解决办法。人们退而求其次,在两个极端方法直接寻找平衡,提出了n路组相联映射(n-ways Set-Associative mapping):
- n路组相联映射(n-ways Set-Associative mapping)
这里n路,是指将Cache分成n个组(set),每一组对应一个地址。也就是说一个地址可以映射到n个Cache Line中。我们举个4 ways的例子。我们先把Cache每4个分成一组:
同样的1GB内存也做出调整:
图片来自HardwareSecrets
可以看出和直接映射很像,不同点在于一个在一组中,第一个没找到,可以找下一个,直到该组的最后一个。这样,可以结合两者的优点。
现实的选择
n-ways Set-Associative,这个n=1,就是直接映射;n=cache大小,就是全相关映射。我们从上面知道两者都不好,而n最好取中间某个值。那么n到底该选几呢?这比较复杂,和Cache的速度和大小、内存的速度、主频等等很多都相关,在很多情况下都是个经验值,也是大量pre-silicon实验的结果。
我们来看看现实生活中L1,L2和L3都是几路相连映射:
AMD
Intel
从中我们可以看出各级Cache选择几路都不一样,而且不同代际之间也会微调。Intel都是2的幂,而AMD则会有3路之类的奇葩路数
六、Cache为什么有那么多级?为什么一级比一级大?是不是Cache越大越好?
通过我们前面的系列文章,大家对Cache的组织形式和特性都有了一定的了解。有个问题不知道大家思考过没有:为什么Cache分这么多级,而是不是直接把L1或者L2增大了事?我们为什么不能直接做出个Cache奇大的CPU呢?下面我们来一一分析。
为什么Cache要分级?
前文(L1,L2,L3 Cache究竟在哪里?)中我们提到CPU中有L1、L2、L3甚至L4级Cache。为什么搞这么麻烦,制程提高,可以放更多晶体管了,CPU厂商直接把L1和L2加倍不就好了吗?
要回答这个问题,首先我们要知道L1和L2 Cache的区别,它们的构造一样吗?答案是否定的,虽然它们都是由CAM(Content Addressable Memory )为主体的tag和SRAM组成的,但是区别却是明显的:L1(先不考虑指令和数据L1的不同)是为了更快的速度访问而优化过的,它用了更多/更复杂/更大的晶体管,从而更加昂贵和更加耗电;L2相对来说是为提供更大的容量优化的,用了更少/更简单的晶体管,从而相对便宜和省电。同样的道理还可以推广到L2和L3上。
在同一代制程中,单位面积可以放入晶体管的数目是确定的,这些晶体管如果都给L1则容量太少,Cache命中率(Hit Rate)严重降低,功耗上升太快;如果都给L2,容量大了但延迟提高了一个数量级:
如何平衡L1、L2和L3,用固定的晶体管数目达成最好的综合效果,这是一种平衡的艺术。在多年实践之后,现在已经相对固定下来,Intel和AMD的L1 Cache命中率,现在往往高于95%,增加更多的L1效果不是很显著,现在更多的是增大L3,以达到花同样的代价,干更多的事的目的。
Cache为什么不会做的很大?
L3现在动辄数十M,比以往那是阔绰很多了,但相对摩尔定律增长的内存容量来说则大幅落后。为什么Cache增长这么缓慢?还是Cost的问题。一个最简单的SRAM就要消耗6个晶体管:
再加上Tag,最少需要数十个晶体管,代价很大。我们花这么大的代价增加Cache,衡量性能的命中率是如何变化的呢?
为简化起见,我们假设L1维持在不到60%的命中率(实际情况95%左右)。从图中可以看出,随着L2容量的增加,开始时L2和整体命中率快速提高,这表明提高L2容量效用很明显。随后L2的命中率在容量增加到64KB后增长趋缓,而整体命中率也同时趋缓,最后甚至基本不大变化了。增加同样的晶体管,而受益却越来越少,出现了边际效用递减的问题。
我们上文(Cache是怎么组织和工作的?)中不同的映射关系会不会使结果不同呢?
图片来源 ExtremTech
从这个图中我们看出不同的映射关系,从直接映射(1 way-Associative)到16路,尽管明显16路更好,但是还是在size达到64KB左右,增加cache size用处不大了。
如此说来,制程进化得来的多余晶体管,在做Cache效益不明显的前提下,还不如把它们拿来做个Core什么的,或者再多做一级Cache!这也是为什么Cache不再增加,而级数增加的原因了。目前我知道Cache size占据Die面积最大的就数这款Pentium M的Die了:
注意左边都被L2 Cache占据,右边还有些L1 Cache,整体大于65%的Die size被用于Cache。
一个脑洞
我们暂时放下讨厌的Cost和制程问题,假设我们有钱任性,做出一个A4纸一样大的L1 cache,把我们尊贵的Core放在正中间,像这样:
我们的L1 Cache可以做到1G,完全不要内存,我们会不会得到一个性能超赞的CPU呢?不幸的是,并不会。因为L1做的这么大,要在一个时钟域内(同步时钟设计远比异步简单)可以访问所有单元,时钟频率做不到很高,而Core因为要在一个周期内操作L1,也不得不放弃3G以上的身价,而大大降低频率。综合下来也许还不如一部分做L1,一部分做L2和L3。这样L1就可以频率很高,Core也不需要自贬身价了。这也从另一方面证明了Cache分级的必要性。
结论
Intel大约每过10年,就会增加一级新的Cache。到现在已经有了L4的Cache。另一方面同样多的晶体管,到底是用来做Cache还是做更好的分支预测器,亦或更多的core,这也在考验设计师的能力。
七、Cache的一致性是怎么保证的?
外置显卡(独显)动辄8G以上显存,很多朋友都希望能够“借”一些给CPU当普通内存用。这在某种程度上是十分容易做到的。显存基本上都会被映射到PCI的mmio地址空间中,一个简单的驱动就可以将它们映射到普通的地址空间中,但如果在其上运行任何banchmark软件你就会发现性能相当差。这固然有GDDR和PC DDR设计初衷不同导致的问题,关于这部分以及之前DDR4的文章末尾部分知友的提问“为什么显存都DDR5了,内存还DDR4”,我后续还有一篇GDDR vs DDR vs HBM的文章来解释,敬请期待,这里就按下不表了。如果我们忽略GDDR的不同,一个进一步的问题就是,为什么不能通过PCIe来扩展普通内存?
主要的原因在于Cache。前一阵举行的“Interconnect Day 2019”,Intel宣布了一系列新技术。其中CXL(Compute Express Link)看起来并不显眼,但却是解决这个问题的关键:
CXL实际上有更大的野心:解决CPU和设备、设备和设备之间的memory鸿沟。普通电脑用户也许偶尔会想到用用显存,用不了也无伤大雅,这个需求并不强烈。但服务器用户有巨大的内存池和数量庞大的基于PCIe运算加速器,每个上面都有很大的内存。内存的分割已经造成巨大的浪费、不便和性能下降。CXL就是为解决这个问题而诞生,我迫不及待得想要给大家介绍这种新技术,但是为了更好的理解它,必须要有些预备知识,也是为什么偷显存性能低的原因:显存不能保证被cache,或者说无法保证cache的一致性。感谢
十年如一日的催稿,我也利用这次机会补上cache系列中缺失的一块拼图,来介绍一下cache一致性的问题。Cache的基础知识可以看这篇文章:老狼:Cache是怎么组织和工作的?zhuanlan.zhihu.com
什么是Cache一致性?
Cache Memory简称Cache,是存储器子系统的组成部分,存放着程序经常使用的指令和数据,这就是Cache的传统定义。在最新的X86 CPU里,cache分为L1、L2和L3,L1一般还分成指令和数据两块,L3有时也被称作LLC(Last Level Cache)。Cache的各个层次之间内容可以是相互包含的(Inclusive),也可以是排斥的(Exclusive)。Inclusive和exclusive cache各有优缺点,比较复杂,以后单独讲,这里提到它们是因为它们和Cache一致性有一定关系,为了简化起见,这里所有相关性都被忽略,将来讲到Cache层级(Hierarchy)再来回顾。
CPU里面L3/LLC实际上被切成很多小片,每个Core对应一个小片:
Haswell-EP
这些小片在Ring bus上都有个Ring stop来连接,Ring bus和Ring bus之间的高速队列将这些L3小片整合在一起,形成一个虚拟的大一统L3。当然在Mesh network后不再有Ring bus,但L3的小片还是存在。我们来看统一后的两路情况:
如果我们不讨论Cache的层级,可以化简成这样:
假设我用红框标出的内存已经被Socket1/Node0和Socket2/Node1访问过了,它的部分数据已经被它们分别cache了。现在socket 1上的一个程序P1改写了一点这些内存中的内容,socket2上的另一个程序P2也要用这段内存。P1的改写和P2的读取如果都仅仅发生在各自的Cache中,就不能保证数据的全局一致性。换句话说就是在一个多处理器系统中,Cache们和内存池可能对同一份数据有多份副本,如何保证这些副本的一致性(Coherency)是个必须严肃对待的问题。
我们可以纯软件来处理这个问题,利用cache操作指令,但开销巨大十分复杂,而且操作系统的内存模型就需要全部改变,这对X86体系甚至绝大多数体系都是不能接受的。所以绝大多数计算机体系都是靠硬件来完成Cache Coherency的,硬件会自动保证各个副本的一致性,不需要软件操心。那么硬件是如何做到的呢?又有哪些弊病呢?
Cache一致性模型
X86、ARM和Power系列的Cache Coherency的原始模型都出自MESI protocol(参考资料2)。在MESI协议中,每个Cache Line(x86中是64 bytes)都有MESI四种状态:
MESI之间的转换可以表示为有限状态机的描述形态:
我并不打算相信介绍各个状态及它们之间的转换,对此有兴趣可以阅读参考资料2和其中的链接。
Intel、AMD和ARM都不是简简单单照搬MESI模型,而是在其上各有扩展,并结合一定的Directory来减小它带来的副作用。Intel的模型叫做MESIF,加了个Forward状态;AMD的模型叫做MOESI,加了个Owner状态。需要特别说明的是,即使同一个CPU,不同Cache层级会有不同的内存模型,这和Inclusive和exclusive密切相关,以后我们再来看有没有机会revisit这点。
Cache一致性发生在哪里?
Cache Line实际上是加了几个bits来表示这些状态。有了这些状态,那么是谁在管理这些状态,各个Cache Line的副本又是谁来同步的呢?在Intel CPU中,这就要引入两个新朋友:HA和CA。
Home Agent(HA),在内存控制器端;Cache Agent(CA),在L3 Cache端。他们都在Ring bus上监听和发送snoop消息。这种模型叫做Bus snooping模型,与之相对的还有Directory模型。Snoop消息会在QPI总线上广播,会造成很大的带宽消耗,为了减小这种带宽消耗,如何snoop有很多讲究,在参考资料1里面有介绍Intel的两种snoop的方式:Home Snoop和Source Snoop。它们的主要区别在于谁主导Snoop消息的发送,HA主导叫做Home Snoop,CA主导叫做Source Snoop。一个跨socket/node的Home Snoop例子:
结语
Intel每一代都在优化Snoop模型,有许多新的机制被引入,并结合Directory,来减小整体的overhead。尽管如此,snoop消耗的QPI带宽依然很高,这在8路变成16路甚至32路时会占据大量带宽,在很多情况下会让更多路变大得不偿失。
现在我们回头看看PCIe为什么不能够被用作真正的内存。因为PCIe和其他所有的设备一样,他们的memory不能被CPU cache。那么为什么不能被Cache呢?因为无法保证Cache一致性。
如前言所述,PCIe内部的memory的割裂性在服务器领域造成了很大问题,CXL的引入为解决这个问题提供了技术手段。加以时日,我相信普通的台式机也可以用上这种技术。关于CXL的介绍,将在下一篇文章中。
后记
评论区一些同学的提问可以看出大家还有不少疑惑,我摘出一些典型的问题:
Q:
PS4只有显存,为啥可以当内存?
A: PS4是只有GDDR5,但它是直接连接APU,并不在PCIe后面。GDDR高带宽、高并发,但延迟较高。PS4选择它是为了PS4里面app很特殊,全是游戏,和GPU需求近似。本文并不是说GDDR不能当内存,而是说显卡的显存(尽管也是GDDR)不能当内存,重点在显卡这里。GDDR vs DDR的事我们今后再讲。
当然这和本文无关,本文主要目标不是GDDR,而是在PCIe后面的显存,甚至其他类型的内存,如NvRAM等等,他们的cache一致性。
Q:
显存延迟高,被cpu调用就要存储速度一致性,这样影响性能,如果反过来,在内存带宽不是瓶颈的情况下,如果gpu占用显存,虽然内存带宽不如显存但他延迟小,所以https://b23.tv/av16369376早期我做的b站上1063爆显存测试上两者实际区别不大,那么我有一个小疑问,gpu调用内存要求显存与内存带宽延迟一致性吗?(从测试结果看不要求)
A: 所谓延迟一致性说法不严谨。GPU可以通过DMA调用内存,甚至可以访问cache。DMA是异步的,不需要原地等待,也不在一个时钟域里面,不会拉底自己访问本地GDDR的速度。
CPU访问GPU后的mmio是一般的访问方式,虽然也不是一个时钟域,但是是同步的和阻塞式的,所以需要等待结束。
CPU访问mmio一般是不cache的,意味着这次访问完,下次还要重新fetch。为什么不cache?因为不知道下次访问该地址内容变了没有,因为GPU的内存不能汇报自己的改变,这就是为什么需要CXL。
八、什么是XMP?
现在的不少土豪朋友不惜重金,买回来高端RGB彩灯内存条。在试过炫彩的灯效之后,普遍感觉最重要的吃鸡速度并没有提升。不是说好的高速条吗,是不是被忽悠了?
其实这些高端内存RGB绚丽的色彩只是外在美,真正重要的是支持JEDEC标准之外的高频率。例如芝奇发布的G.Skill系列最高支持的频率可达4700MHz,而我们一般的DDR4内存才2400MHz, 高的也就2666MHz,相差几乎一倍!并支持CL19-19-19-39的第延迟。关于内存条的基础知识可以参考专栏里面另外几篇文章:
老狼:内存系列一:快速读懂内存条标签zhuanlan.zhihu.com老狼:内存系列二:深入理解硬件原理zhuanlan.zhihu.com
老狼:内存系列三:内存初始化浅析zhuanlan.zhihu.com
我们今天主要介绍这些高端内存支持的XMP技术,更加重要的是这种技术并不是即插即用(PNP)的,很多情况下需要手动开启,我们也会介绍如何开启它。
什么是XMP?
XMP全称是Intel Extreme Memory Profile。是Intel在2007年9月推出的内存认证标准。它适用于DDR3和最新的DDR4。Intel宣称可以”让您对RAM 和可兼容的 DDR3/DDR4 内存进行超频。“
在XMP技术出现之前,内存的超频已经广泛存在了。需求首先来自游戏玩家,他们真的在实践奥运精神,要求更快、更强,以便在联机游戏里面更好的虐别人。为此,内存厂商为此生产了各种游戏内存,可以工作在其默认频率之上。但那时这种内存条兼容性比较差,游戏玩家不得不在BIOS里面反复调整各种时序,才能稳定的运行游戏。各种主板的兼容性也存在很大问题,这种主板可以工作,别家出的就不一定可以。
Intel感受到了这种市场的需求,在2007年9月推出XMP内存认证标准。它的原理是在SPD上扩展了两组profile。
SPD是每个DIMM上都的,一块小的存储芯片(EEPROM),上面详细记录了包括CL-tRCD-tRP-tRAS-CMD等等很多参数,还有生产厂家的代码等等,这也是BIOS为什么能知道我们插了哪种内存的原因。
第一组profile一般是标称的频率速度,也就是高频条包装上保证能够达到的速度。第二组一般是更高的极限频率。
内存厂商负责验证这两组profile和不同芯片组的兼容性,并把内存及该设定送交Intel测试。Intel测试后会予以XMP认证,并公布在官方网站上(参考资料1).
它的工作原理十分简单直接,BIOS的内存初始化程序负责从SPD中读取该XMP数据块。并按照其要求而不是training的结果设置各种参数。
如何开启XMP
要开启XMP,必须进入BIOS。如何进入BIOS见:
老狼:如何进入BIOS?zhuanlan.zhihu.com
在BIOS中,XMP的开启位置千奇百怪,有的在内存菜单中,有的在超频菜单中,需要读者自己仔细寻找。下面是几个例子:
其他
怎么知道自己XMP开启没开启,开启后效果如何呢?可以用cpu-z来测试一下内存的频率和参数。
AMD借鉴了XMP,也有类似的技术,叫做“AMP”–AMD Memory Profiles。不过有些主板厂商选择直接支持XMP。