原文:为什么CPU有多层缓存

http://mp.weixin.qq.com/s?__biz=MzI1NDM2Nzg5Mw==&mid=2247483712&idx=1&sn=5c95353a0311df340fb51e4f064b34e9&scene=2&srcid=0817T20QrQwrjmDnhQMt3MXu&from=timeline&isappinstalled=0#wechat_redirect

译者介绍:杨川,英文名Jerry,就职于IBM全球服务中心。

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

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

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

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

缓存的故事

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

你有一个办公桌(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’)。 在芯片里移动数据实际上是一个物流问题,并且超级复杂。

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

对『Hacker时间』感兴趣的同学可以扫码进群一起来讨论。

【转载】为什么CPU有多层缓存的更多相关文章

  1. 转载:CPU的位数和操作系统的位数

    1. 32位系统最大只能使用3.5G的内存,而64位系统最大能够使用128G内存. 2. 32位CPU只能安装和使用32位.16位的系统和软件,无法使用64位系统及软件. 3. 64位可以安装64位系 ...

  2. Java内存模型深度解读

    Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的.Java虚拟机是一个完整的计算机的一个模型,因此这个模型自然也包含一个内存模型——又称为Java内存模型. 如果你想设计表现良好的并发 ...

  3. Java内存模型---并发编程网 - ifeve.com

    Java内存模型 转自:http://ifeve.com/java-memory-model-6/ 原文地址  作者:Jakob Jenkov 译者:张坤 Java内存模型规范了Java虚拟机与计算机 ...

  4. cpu,内存,虚拟内存,硬盘,缓存之间是什么关系??

    1.CPU即中央处理器,是英语“Central Processing Unit”的缩写.CPU从内存或缓存中取出指令,放入指令寄存器,并对指令译码分解成一系列的微操作,然后发出各种控制命令,执行微操作 ...

  5. cpu缓存与多线程

    一.cpu缓存结构 CPU速度远高于内存(即如果只考虑CPU和内存因素,程序的性能常常受到内存访问速度的限制,内存访问和运行),为了协调CPU和内存在速度上的差异,在CPU中增加了高速缓存.和计算机存 ...

  6. java cpu缓存

    众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存比CPU慢很多. 其实在30年前, CPU的频率和内存总线的频率在同一个级别, ...

  7. 从Java视角理解CPU缓存(CPU Cache)

    从Java视角理解系统结构连载, 关注我的微博(链接)了解最新动态众所周知, CPU是计算机的大脑, 它负责执行程序的指令; 内存负责存数据, 包括程序自身数据. 同样大家都知道, 内存比CPU慢很多 ...

  8. 浅谈CPU三级缓存和缓存命中率

    CPU: CPU缓存(Cache Memory)是位于CPU与内存之间的临时存储器,它的容量比内存小的多但是交换速度却比内存要快得多.缓存的出现主要是 为了解决CPU运算速度与内存读写速度不匹配的矛盾 ...

  9. 【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之缓存融合技术和主要后台进程(四)

    缓存融合技术和主要后台进程(四) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...

随机推荐

  1. QuickFlow UI 控件之 NamedFormAttachment

    在开发自定义表单时,如果碰到需要按类别上传附件的情况,(比如流程附件分为草稿版,正式版,发布版),比较难处理,需要开发自定义字段控件来实现. QF最新版本(Build131124)提供了NamedFo ...

  2. MyBatis 查询记录时日期字段没有时分秒

    今天发现如果表里面的字段为Date类型时,程序查询出来的数据只有年月日 搜索了下,发现在resultMap里面把这个字段的jdbcType原先为Date,改为Timestamp就行了. 确实可以.

  3. 【hadoop2.6.0】安装+例子运行

    由于下载的是hadoop的最新版,网上各种杂七杂八的东西都不适用.好在官网上说的也够清楚了.如果有人看这篇文章的话,最大的忠告就是看官网. 官网2.6.0的安装教程:http://hadoop.apa ...

  4. linux 添加新硬盘的方法

    在服务器上把硬盘接好,启动linux,以root登陆. 比如我新加一块SCSI硬盘,需要将其分成三个区: #fdisk /dev/sdb 进入fdisk模式: Command (m for help) ...

  5. 转:关于垂直网格与CSS基线对其的探讨

    网页设计布局中一直比较流行网格对齐,但只是针对水平的对齐,很少或者没有涉及垂直对齐,这篇文章很详细的讲解了垂直网格,乃至基线对其的相关,而css3中的多列布局的也使其显得更为重要,因此还是很有必要去了 ...

  6. css小tip

    1. <input>标签的默认样式 当在页面中添加一个input标签,当点击输入框时会有一个外边框包裹着,可以使用 : input { outline: none} 去除点击时产生的外边框 ...

  7. Android Studio系列教程二--基本设置与运行

    Android Studio系列教程二--基本设置与运行 2014 年 11 月 28 日 DevTools 本文为个人原创,欢迎转载,但请务必在明显位置注明出处! 上面一篇博客,介绍了Studio的 ...

  8. Swift Tips - Array 类型

    在开发中,数组这个概念我们应该很熟悉了,Objective-C 中为我们提供了 NSArray 作为数组的实现.大家应该对很熟悉了.而在 Swift 中,为我们提供了它自己对于数组的实现,也是这里我们 ...

  9. systemtap 技巧系列 +GDB

    http://blog.csdn.net/wangzuxi/article/category/2647871

  10. [LeetCode#128]Word Ladder II

    Problem: Given two words (start and end), and a dictionary, find all shortest transformation sequenc ...