多语言展示
当前在线:1408今日阅读:133今日分享:12

处理器高速缓存的工作原理

处理器高速缓存是评定CPU性能的重要指标,下面就简单介绍下高速缓存的相关知识。目的是希望大家对这个概念有个大致的了解。
方法/步骤
1

处理器高速缓存历史篇:1985研发的386DX,第一次把缓存技术运用在处理器上,但当时的缓存器在处理器的外面。九十研发486DX,把高速缓存器集成到处理器中,大小有8K,并称为1级缓存L1,同时主板上的高速缓存称为二级缓存L2。1993年英特尔推出Pentium系列,首次把一级缓存拆分成一级指令缓存(L1I)和一级数据缓存(L1D)。二级缓存不变,仍集成在主办上。后续AMD公司相继推出K5、K6、K6-2处理器延续同样的X86体系结构。K6-3推出了3级缓存L3。L2在处理器外,处理器访问速率很低,从486DX2 CPU开始处理器存取内部数据的速率就不同于处理器存取外部数据的速率。例如工作在200兆赫Pentium-200,内部频率200兆赫,但其二级缓存(外部)的频率L2只有66兆赫。1996推出了最新一代的第六代X86系列CPU——P6,把二级缓存芯片封装入处理器中。这种体系结构沿用到现在,把一级和二级高速缓存集成在CPU内部,运行于CPU内部的时钟频率。CPU的型号决定了其高速缓存的大小,除了更换CPU,没有其它的方法增加高速缓存的大小。

2

初识处理器高速缓存:下图是处理器取出指令过程的简化图,当然实际的过程会根据具体CPU类型的不同而变化。图中虚线部分表示CPU内部,有3个高速缓存。L 2:一般单位大小在几百KB,建立在内存和L1I(一级指令缓存)之间,存储指令和数据。L1:大小在白百KB以下。L1 I:一级指令缓存,存储供处理器执行的指令。L1D:一级数据缓存,存储写回内存中的数据。其中一级缓存离处理器的执行单元较近。不可能做出没有延迟的静态内存,特别是在CPU运行在一个高速的时钟频率中,制造者将这种延迟极低的内存只用在一级高速缓存中,不用于二级缓存,所以二级缓存会有更多延迟,也会比一级缓存存取速率慢。仔细观察下图,你会发现一级指令缓存是投入口,一级数据缓存是产出口。一级指令缓存很擅长于处理循环结构,因为离取指单元很近。一级指令缓存也存储指令之所要处理的数据,以便于解码。这些数据取绝于CPU的通过预译码器来确定将,然后储存在一级指令缓存中,所以一级指令缓存要比出厂值大,因为制造商没有加入每条额外数据所占用的空间。此外还有出现过基于其它体系结构的处理器,他们没有L1指令缓存。例如基于Netburst微体系结构的奔腾4,奔腾D,奔腾4至强和奔腾4的赛扬处理器。他们有一个跟踪执行缓存,位于解码单元和执行单元之间,存储解码指令。因此,L1指令缓存是存在的,只是有不同的名称和不同的位置。提到这一点,因为这是一个非常常见的错误,认为奔腾4处理器没有L1指令缓存。因此,当比较奔腾4到其他CPU时,人们会认为它的L1缓存要小得多,因为它们只计算了8 KB的L1数据缓存。跟踪执行缓存的实际大小为150KB。

3

多核处理器内的二级高速缓存:多核CPU中的L2缓存体系结构变化很大,取决于CPU模型。基于K8架构的奔腾D和AMD双核心处理器,每个CPU核心都有自己的L2高速缓存。所以每个核心工作起来就像是一个完全独立的CPU。基于Pentium M的微体系结构英特尔双核心处理器,有一个共享L2高速缓存。认为共享体系结构更好,因为有两个独立缓存空间会出现利用率不一致的问题。另一方面,英特尔四核CPU:酷睿 2 Ex和酷睿2-四核,使用两个双核心芯片,这意味着共享只发生芯1和2和3和4之间。当时英特尔计划使用单个芯片控制四核CPU。即使用L2缓存在四个核心之间共享。下图中,可以看到使用这三种L2内存缓存解决方案之间的比较。基于K10架构的AMD处理器在CPU内部有一个共享的三级高速缓存L3,结合以上两种方法,示意图如下第二张图,这个缓存的大小将取决于CPU模型,功能类似于L2。

4

高速缓存的工作原理:CPU取指单元从一级指令缓存中获取将要执行的指令,如果获取不到,将在二级缓存中获取,仍获取不到的话,就必须从内存中获取指令。CPU从高速缓存中获得所需的指令或数据,称之为“命中”,相反CPU在高速缓存中获得不到所需要的指令或数据,必须直接从内存中获取的情况,称之为“丢失”。当然,当你开机时高速缓存是空的,所以访问内存是必需的-会不可避免的出现“丢失”。但是在第一个指令被加载之后,高速缓存的表演开始了。当CPU从内存某个位置加载指令时,一个称为缓存控制器的小的数据块,会加载入高速缓存内,它标记最近一次CPU加载指令的内存地址。因为程序经常顺序地执行,所以CPU将请求的下一个内存地址可能是它刚刚加载的内存地址下一个单位的地址。所以缓存控制器会提前加载一些该地址中的数据,因此CPU不需要到外面去访问数据,它已经加载在嵌入式CPU中的缓存控制器中,并以CPU内部的传输速率进行存取。缓存控制器存储的数据量称为“行”,长度一般64位字节。除了加载少量的数据外,内存制器会试图猜测CPU接下来会访问的地址。有一种称为预取器的电路,它所做的是:当内存中前64位字节加载入缓存控制器后,如果程序还需要以顺序的方式从内存位置加载指令和数据,那么就通过预取器把CPU下一个请求的指令和数据加载到高速缓存中。下面我们总结下高速缓存的工作方式:1.CPU要求在地址“A”中存取指令/数据。2.如果地址“A”的内容不在高速缓存中,CPU必须直接从内存中获取它。3.缓存控制器将一行(通常为64字节)从地址“A”开始加载到高速缓存中。这比CPU请求的数据要多,所以如果程序继续按顺序运行(也就是请求地址A + 1),CPU将请求的下一个指令/数据将被加载到缓存中。4.通过一种称为预取器的电路加载更多的数据,即从地址+ 64开始加载数据。例如:奔腾4 CPU有一个256字节的预取器,所以接下来的256个字节的数据将加载到高速缓存后面。如果程序总是按顺序运行,CPU将永远不需要直接从内存中获取数据——除了加载第一个指令,因为CPU需要的指令和数据总是在CPU请求之前存储在内存缓存中。但是程序不会像这样运行,时不时地从一个内存位置跳到另一个内存位置。缓存控制器的主要处理猜测CPU将跳转到什么地址,在CPU请求之前,将这个地址的内容加载到内存缓存中,以免CPU访问内存,减慢系统的速度。这个作业叫做分支预测,所有的现代CPU都有这个特性。现代CPU的命中率至少为80%,这意味着CPU至少有80%的时间没有直接访问内存,而是高速缓存。

5

高速缓存的存储组织方式:内存缓存被划分成行,每一个存储在16到128个字节之间,取决于CPU。大多数CPU,内存缓存被组织成64字节的行(512位),因此使用64字节行的内存高速缓存来举例。因此,一个512 KB的L2内存缓存分为8192行。请记住,1 KB是2的10次方或1024字节,而不是1000字节,所以是524288/64=8192。在我们的示例中,我们将考虑一个具有512 KB L2内存缓存的单核CPU。下图中,我们演示了内存缓存内部组织。内存缓存可以三种不同的结构下工作:直接映射,全相联和组相联(即n路组相联)。后者是目前使用最多的结构,下面让我们来看看这三种配置是如何工作的。直接映射:直接映射是创建内存缓存的最简单方法。在这种配置中,内存被划分为高速缓存中的相同行数。如果我们有一个有1 GB RAM的系统,这个1 GB将被划分成8192个块(假设内存缓存使用我们上面描述的配置),每一个都有128 KB(1/8192=131072)——记住1 GB是2×30字节,1 MB是2×20字节,1 KB是2×10字节)。如果我们的系统有512兆字节,内存也会被分为8192个块,但是这一次每一个都有64 KB。一词类推,下面第二张图中演示了这个组织。直接映射的主要优点是它是实现最简单。当CPU要从内存指定地址(如地址1000),缓存控制器负载(64字节)的内存数据并存储在高速缓存(即地址1000到1063,假设我们使用的是8位寻址方案只是帮助我们的例子)。因此,如果CPU再次请求这个地址的内容或地址后面的地址(即,从1000到1063的任何地址),它们将已经在缓存中。问题是,如果CPU需要两个地址映射到同一个缓存行,就会出现缓存丢失(这个问题称为冲突)。继续我们的示例,如果CPU请求地址1000,然后询问地址2000,则缓存丢失将发生,因为这两个地址在同一块(前128 KB)内,缓存内是从地址1000开始的行。因此,缓存控制器将从地址2000加载该行,并将其存储在内存缓存的第一行,清理以前的内容,在我们的例子中,地址1000的行。问题还在继续。如果程序的循环长度超过64字节,则循环的整个时间段都会产生“丢失”。例如,如果循环从地址1000到地址1100,CPU将不得不通过循环的持续时间从内存直接加载所有指令。因为高速缓存是从地址1000到1063的内容,当CPU要求从地址1100的内容,它将不得不去访问内存,而缓存控制器将加载地址1100至1163。当CPU请求返回访问地址1000时,它必须返回到内存中去访问,因为缓存不再包含地址1000的内容。如果这个循环执行1000次,CPU将不得不到RAM内存1000次。这就是为什么直接映射缓存是效率最低的缓存配置,并且个人电脑上已经不在使用这种存储方式。全相联:在全相联的配置上,一方面高速缓存的行与内存位置之间没有硬连接。缓存控制器可以存储任何地址。因此上述问题不会发生。这种配置是最有效的配置(即命中率最高的配置)。另一方面,控制电路要复杂得多,因为它需要跟踪内存缓存中的内存位置。这就是为什么混合解决方案也被称为集合关联,是当今最常用的方法。

6

n路组相联高速缓存:在这个方案中,内存缓存被分成几个块(组),每个块包含“n”行。所以在一个4路组相联高速缓存内存缓存将有2048块包含四行每行(8192线/ 4),在2路组相联高速缓存内存缓存将有4096块。一此类推。然后,主内存被划分为高速缓存中可用的相同数量的块。保持512 kb的4路组相联的例子,主内存将分成2048块,块内的可用内存缓存数量相同。每个内存块都与缓存中的一组行链接,就像在直接映射缓存中一样。在1 GB RAM中,内存将被分成2048个块,每512个字节。该映射与直接映射发生的情况非常相似,不同的是,对于每个内存块,在内存缓存上有不止一行可用。每行可以从映射块中的任何地址保存内容。在一个4路组相联缓存每个设置内存缓存可以有相同的内存块。通过这种方法,直接映射缓存所带来的问题已经消失(我们在前面的页面中描述了碰撞问题和循环问题)。同时,集合关联缓存比全相联高速缓存更易于实现,因为它的控制逻辑更简单。正因为如此,这是目前最常见的缓存配置,尽管和全相联相比性能较低。关于集合数量和内存块大小之间的完美平衡,有很多学术讨论,并且没有明确的答案——英特尔和AMD也使用不同的配置方法。这里只是把CPU高速缓存做一个简单的历史和概念的介绍。希望大家对此有个简单的了解。

推荐信息