CPU缓存的作用 CPU有多层缓存有何用意

描述

这是来自于‘jlforrest’的一位读者的提问,我认为值得更详细的解答。以下是他的问题:

● 我理解缓存,但不明白为什么需要多层缓存而不是直接用一层大的。换句话说,如果一级缓存是32K,二级256K,三级2M,为什么不用32K+256k+2M的一级缓存?

简短的回答是不同的缓存级别适用于不同的目的和限制,在设计上完全不同。经验上,随着缓存级别的增加,缓存变得更大,更慢,密度更高,每单位存储消耗的电能更少,能处理更多的任务。

CPU的缓存有什么作用?

高速缓存是处理核心(包括CPU与GPU)或者外部储存设备与主内存区间的一个缓冲储存区,所以称为缓存

在CPU,GPU等处理核心上,核心计算的临时中间数据和大量需求的数据都优先储存在缓存里,举个例子:CPU计算一个1+1+1的值时,第一次计算前两个数的和的结果2就储存在CPU缓存里,再把结果拿来进行第二次计算,当然,现在的处理器算这个数据不用这么做,只是面对大量数据计算的时候需要这么做

在更大量的计算里,处理器会按数据的优先级从低到高分别储存在一级,二级,三级缓存中,再没有空间就会放进内存中,处理器读取数据也是从一级缓存开始,直到内存中,如果内存还没有数据就去硬盘光盘等外部储存设备找,一级缓存速度最快,二级,三级次之

在外部储存设备中,比如硬盘和光驱的缓存主要是提高传输速率,增加硬件寿命,你可以从硬盘一个分区复制一堆小文件到另一个分区,你可以发现,复制相同容量的文件速度是大文件快于小文件,因为每个小文件都要进行文件的建立,数据写入与结束写入等过程会耗费很多时间

在处理器或者内存向硬盘或者光驱(刻录机)写入的数据都是小文件或者数据而且并不连续,他们都先放在硬盘缓存里,到整个文件结束或者到缓存区容量极限时再一次性写入硬盘,这样可以减少硬盘的读写次数,并且以此写入的速度更快~

cpu缓存现在都分两个级别,一及缓存称L1 cache,二级缓存称为L2 cache.

当然对于不同cpu,两及缓存的作用是不同的。但总体来说,缓存是储存cpu急需处理的数据的地方,当cpu要处理东西的时候,缓存中就开始储存这些数据,由于缓存速度非常之高,所以,cpu读取这些数据的速度就相当快。

由于缓存容量相当小,但是当缓存中的数据处理完了又没有来得及重新添满的时候,或者是缓存中的数据不是cpu马上要处理的数据的时候,cpu就只有跳过缓存,直接村内存读取,内存的速度要相对慢得多,所以这个时候cpu整体的速度就下降了。

当然,AMD和intel在缓存上的结构完全不同,这个造成了为什么intel的主流处理器的L2 cache缓存在2-4Mb,而AMD的L2 cache只有256kb-512kb.这个我们就要说到他们L1 cache的区别了。

intel的L1中不储存cpu要处理的实际数据,他储存的都是L2中数据的目录,也就是intel的cpu要处理数据的时候先要访问L1,为的是了解他要储存的实际数据在L2中具体的位置。这个大大减少了cpu寻找L2数据的时间。比喻起来,intel的L2是一个仓库,L1关于就是这个仓库中储存东西具体位置的目录。

AMD完全不同,L1中就储存实际数据,L2也储存实际数据,当L1中的数据用完了的时候,或者L1不能装的过大的数据的时候,cpu就直接处理L2中的数据。比喻起来,AMD的L1是个小仓库,L2是个大仓库。

然后是为什么他们对L2需求不同。

AMD的很好理解,他cpu处理数据的时候是有续处理的,先处理L1,处理完了再处理L2,数据一个接一个。

intel采取的是则是乱处理方式,cpu不会衣顺序处理数据,而是随即挑选数据来处理,当他随便挑选的数据在L2中时,他就读取L1了解数据在L2的位置,然后处理这个数据,但是当数据不在L2中时,就读取内存。

这个造就了他们L2大小不同,intel的处理方式像是一个人随机的在扔飞标,飞标落在标盘每个地方的几率是相同的,标盘内的红心就是L2的数据,标盘的其他地方是内存。前面说了,L2中数据是高速的,只有处理L2的,才能更快,否则要慢很多。所以,一个随机扔飞标的人为了让飞标落在红心的几率更大,最好的办法就是加大红心的面积,也就是L2.因此为了提高cpu的速度,intel需要很大的红心,也就是L2.

AMD则不同,他是一个接一个处理的,不是随机的扔飞标,他要考虑的只是L1和L2中单个数据的大小,因为cpu要处理的数据几乎都在0-2Mb之间,0-128kb的占了50%,128-256kb占了25%,256-512的占了24%,大于512kb的只占了1%.

因此,512kb就能满足cpu几乎所有的需求了,只有处理那些1%的大于512kb的数据的时候AMD才会访问内存。因此AMD需求很小的L2.

为了把这个问题讲得更直观,我打算用一个有点奇怪但很精巧的类比:

缓存的故事

假设你是一位六十年代的白领,在巨大的办公楼里工作,没有电脑,你需要阅读大量的文件并且交叉检索这些文档。

你有一个办公桌(L1 缓存)。桌上的文件是你正在手头处理的资料,还有一些是你最近看过的或者你准备阅读的。通常我们需要阅读文件的每一页(对应于存储单元的一个字节),但除非它们在办公桌上,文件都是作为一个整体。即只想看某一页的内容,我们也必须把整份文件抓过来。

办公室里还有文件柜(L2 缓存)。这些文件柜里存放的是你最近处理过,但目前没有在使用的文件。办公桌上的文件在用完后,通常也会放回文件柜。从文件柜里拿文件就不是顺手拈来了——你需要走过去,打开相应的抽屉,还要查目录卡片,才能找到想要的文件——不过这也还比较快了。

有些时候,其他人也需要查看你的文件柜里的文件。勤杂工会推着一辆推车(环路公共汽车)在各个办公室转。如果有人在自己的文件柜没有找到相应的资料,他会写一个纸条交给勤杂工。为简化起见,假设这位勤杂工知道所有的东西放哪儿。所以当他来到你的办公室的时候,他会检查你的文件柜里是否有其他人需要的文件,如果有,就把这些文件抽出来放到车上。当他转到别的办公室,就会把找到的文件放在文件柜里,并留下收条。

有时候,这些文件并不在文件柜里,而是在办公桌上。那就不可以直接拿了,需要征询主人的意见,如果不行,大家就要商量如何协调。有大量冗长的详尽的合作指引来处理这类情况(至少要一起开会)。

文件柜经常会满,这时就不能放新的文件,需要先腾地方,把一些很久都没用到的文件拿出来。勤杂工会把这些文件放到地下室里(L3 缓存)。地下室里的文件被密集地堆放到纸箱里或者文件架上,交给文档管理员处理,其他人都不会下去,也不会了解文档的存放细节。

当勤杂工来到地下室,会把一堆不需要的文件放到‘in’框里,同时他也会留下一堆纸条,写着在楼上文件柜里找不到的文件名。文档管理员会拿着这些纸条,找到对应的文件,把它们放到‘out’ 框里。下次勤杂工下来的时候,就可以把‘out’框里的文件拿走,交给需要的人。

现在的问题是,文件还是太多,地下室也放不下,而且办公大楼的租金都很贵,所以通常公司都会在离市区较远的地方租一个仓库来存放归档文件(对应于DRAM内存)。文档管理员会记录哪些文件放在地下室,哪些文件放在仓库。这样,当需要拿文件时,管理员就知道哪些是能在地下室找到,哪些要到仓库里拿。每天有一两次,会有一辆货车开到仓库去拿需要的文件,同时把一些地下室的旧文件运过去。

对勤杂工而言,他并不关心这些细节,这些都是文档管理员在处理。他需要做的就是把纸条放到‘in’框里,从‘out’框里取出文件。

回到最初的问题

那么,这个类比的意义何在?简短而言,一个具体的模型比模糊的概念更能清晰地阐明物流的意义。实际上,物流对设计芯片的意义和运作一个高效的办公文件处理系统是一样的。

最初的问题是‘为什么不用一个大的缓存,而是用几层小的缓存?’。 也就是说,如果一个4核芯片配置32K一级缓存,256K二级缓存和2M三级缓存,为什么不能用一个3M的大缓存?

在类比里,类似于问与其给4个人每人分一个1.5米宽的办公桌,为什么不给这4个人一个150米宽的大办公桌?

关键在于,放办公桌上的目的就是要能触手可及。如果办公桌太大,就没有意义了。难道还需要走50米去拿文件? 对一级缓存也是同理,如果太大,存取速度会变慢,而且会消耗更多的电力。所以一级缓存既要足够大到能起作用,又要小到能够快速存取。

另外一点,一级缓存处理的存取类型和其他缓存不同。有L1的数据缓存,也有L1指令缓存。Intel的CPU还有另外的指令缓存,uOp缓存,既叫L1并发指令缓存也叫L0指令缓存。

L1数据缓存通常只处理1到8个字节的数据,但高层级的缓存并不处理单独的字节。在我们的类比里,所有不办公桌上的资料都是以文件为单位(对应于catch line)。 在内存中也一样,高层级缓存通常是批发处理数据,以缓存行为单位(cache line)。

L1指令缓存和数据缓存完全不同,就内核而言,它是只读的。(指令内存的写入通常是用非直接的方式,先把指令放入高层的缓存,再载入一级指令缓存)。由于这个原因,指令缓存和数据缓存通常是分隔的。使用通用的L1缓存意味着把互相冲突的设计原则糅合在一起,妥协的结果就是任何一个目的都达不到。而且用通用的L1缓存处理指令和数据负载也会很大。

另外,作为程序员,我们通常不关心内存带宽。例如,每个时钟周期,i7的CPU的内核能从L1缓存中读取16字节的指令,而且会不断地循环读取。如果是3GHZ,每个核可以读50GB指令/秒。实际上,通常L1指令缓存的能力都足够大,很少需要L2缓存参与处理。但如果是通用缓存,就需要预估指令和数据的高并发情况。(想象一下在L1缓存中用memcopy拷贝几K数据的情况)

顺便提一句,如果都在L1缓存,CPU能在一个时钟周期完成许多存取操作。‘Haswell’或者之后的3GHZ的i7内核可以处理超过300GB的指令和数据, 如果搭配合理的话。这样的处理能力绰绰有余,但你仍然需要考虑数据和指令同时出现峰值的情况。

L1缓存在设计上就是越快越好,以应对峰值情况。只有L1缓存处理不了,才会转给更高层的缓存,但速度会降低。因为高层缓存更关心电力效率和存储密度。

第三点,共享。在上面的比喻中,独立办公桌,亦或L1缓存是私有的,如果在你的办公桌上,你只管拿就好了,不需要询问其他人。

这很关键。如果4个人共享一个大办公桌,你就不能随便拿文件,因为另外三个人可能正在使用。(即使他们只是在阅读其他文件时顺便参考一下你想使用的文件)。任何时候,你想要拿什么东西,你需要先叫一声,‘有人在用吗?’如果别人在你前面,你就必须等待。或者需要一个排队系统,当存在资源冲突的时候,每个人需要拿张票排队等候,或者其它的什么机制,具体实现细节并不重要,但是所有的事情你都需要和其他人协调。

对多核共享缓存的情况也是这样。你不能在不通知别人的情况下随意动那些数据,所有对共享缓存的操作都必须协调进行。

这就是为什么我们要使用私有的L1缓存。L1缓存就是你的办公桌,你可以随便使用桌上的文件。L2缓存处理大部分的协同操作。大部分时间,工作者(CPU内核)坐在办公桌前,勤杂工会走过来,把需求列表拿走,同时把之前你想找的文件放倒文件柜里。整个过程不会打断你的工作(CPU)。

仅仅当你和勤杂工都需要拿文件柜里的同一份文件,或者别人想用你办公桌上的文件,这时就需要停下手头工作,进行交谈。

简单而言,L1缓存的工作就是优先为CPU内核服务。因为是私有的,所以基本不需要协调工作。L2缓存也是私有的,但是它的工作重心还包括在不打扰内核工作的情况下,处理大量的缓存间的数据通信。

L3缓存是共享资源,需要全局协调。在上面的类比中,工作者只有从勤杂工的推车里拿到文件,这就是一个阻塞点。我们只能希望L1和L2缓存足够大以便这类阻塞点不会成为性能瓶颈。

附加说明

本篇文章涵盖了当前台式机(笔记本)CPU的缓存架构:分开的L1/L1 D 缓存,每核统一的L2缓存,共享的L3缓存。

不是每个系统都象这样。一些系统并不区分指令缓存和数据缓存;另外一些则把指令和数据在所有的缓存级全部分开。很多L2缓存是多核共享的,L2缓存就象是连接多个内核的公共汽车。还有一些系统有L3和L4缓存。我也没有提到使用多CPU套接字的系统。

我提到环路公共汽车是因为这是一个很好的类比。环路公共汽车很常见。有些时候,环路汽车是个麻烦(尤其是只需要把两三个街区连起来);有时候,环路公共汽车需要和交叉系统连接起来(就象在办公室,每个楼层用推车,不同楼层则用电梯)。

作为软件工程师,我们自然而然地会假设模块A和模块B可以魔术般地连接,数据则可随意地从一端流向另一端。内存的实际工作机制其实非常复杂,但抽象出来呈现给程序员的只是一组大平面的字节排列。

硬件并不象这样工作。各个部件之间并不能魔法般地自动连接。模块A和模块B并非抽象概念,而是具体的物理设备,实际上可以看作是非常小的机器,在硅片上占有实际的物理空间。芯片都有平面图,是真正的2D地图。如果你想连接A和B,就需要一条实际的导线来连接。 导线也占空间,而且需要消耗电力(越远消耗越多)。用一大捆线连接A和B意味着物理上这一块区域会阻碍其他区域的连接。(当然,芯片可以使用多层连接,如果你有兴趣,可以搜索‘routing congestion’)。 在芯片里移动数据实际上是一个物流问题,并且超级复杂。

所以尽管办公室的故事只是半开玩笑的类比,‘谁需要和谁谈’、‘这个系统的几何构造如何——是有意义的布局吗?’这些问题其实对系统设计和硬件相关并有巨大的影响。 利用空间的隐喻来概念化实际情况是十分有效的。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分