关于cup cache的理解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Kair_Wu/article/details/48469387

关于cup cache的理解

 

从给老婆买电脑说起

我们知道计算机的计算数据需要从磁盘调度到内存,然后再调度到L2 Cache,再到L1 Cache,最后进CPU寄存器进行计算。

给老婆在电脑城买本本的时候向电脑推销人员问到这些参数,老婆听不懂,让我给她解释,解释完后,老婆说,“原来电脑内部这么麻烦,怪不得电脑总是那么慢,直接操作内存不就快啦”。我是那个汗啊。

我只得向她解释,这样做是为了更快速的处理,她不解,于是我打了下面这个比喻——这就像我们喂宝宝吃奶一样,

  • CPU就像是已经在宝宝嘴里的奶一样,直接可以咽下去了。需要1秒钟
  • L1缓存就像是已冲好的放在奶瓶里的奶一样,只要把孩子抱起来才能喂到嘴里。需要5秒钟。
  • L2缓存就像是家里的奶粉一样,还需要先热水冲奶,然后把孩子抱起来喂进去。需要2分钟。
  • 内存RAM就像是各个超市里的奶粉一样,这些超市在城市的各个角落,有的远,有的近,你先要寻址,然后还要去商店上门才能得到。需要1-2小时。
  • 硬盘DISK就像是仓库,可能在很远的郊区甚至工厂仓库。需要大卡车走高速公路才能运到城市里。需要2-10天。

所以,在这样的情况下——

  • 我们不可能在家里不存放奶粉。试想如果得到孩子饿了,再去超市买,这不更慢吗?
  • 我们不可以把所有的奶粉都冲好放在奶瓶里,因为奶瓶不够。也不可能把超市里的奶粉都放到家里,因为房价太贵,这么大的房子不可能买得起。
  • 我们不可能把所有的仓库里的东西都放在超市里,因为这样干成本太大。而如果超市的货架上正好卖完了,就需要从库房甚至厂商工厂里调,这在计算里叫换页,相当的慢。

我讲完后,老婆看似有些明白了,然后对我说,“明白了,我就说最近衣服有点跟不上,原来是L1(衣柜)里的衣服跟不上了,老公什么时候去买衣服啊……”。我晕!(来自网络)

基本概念

计算机系统中,CUP缓存(CPU cache)适用于减少处理器访问内存所需要的平均时间的部件。在金字塔式存储系统中位于自顶向下第二层,仅次于CPU寄存器。其容量远小于内存,但是速度却可以接近处理器的频率。缓存之所以有效,主要是因为程序运行时对内存的访问呈现局部性(Locality)特征。这种局部性既包括空间局部性(Spatial Locality),也包括时间局部性(Temporal Locality)。有效利用这种局部性,缓存可以达到极高的命中率。在处理器看来,缓存是一个透明部件。因此,程序员通常无法直接干预对缓存的操作。但是,确实可以根据缓存的特点对程序代码实施特定优化,从而更好地利用缓存。

缓存的存储结构

结构上,一个直接映射(Direct Mapped)缓存由若干缓存块(Cache Block,或Cache Line)构成。每个缓存块存储具有连续内存地址的若干个存储单元。在32位计算机上这通常是一个双字(dword),即四个字节。因此,每个双字具有唯一的块内偏移量。

每个缓存块有一个索引(Index),它一般是内存地址的低端部分,但不含块内偏移和字节偏移所占的最低若干位。一个数据总量为4KB、缓存块大小为16B的直接映射缓存一共有256个缓存块,其索引范围为0到255。使用一个简单的移位函数,就可以求得任意内存地址对应的缓存块的索引。由于这是一种多对一映射,必须在存储一段数据的同时标示出这些数据在内存中的确切位置。所以每个缓存块都配有一个标签(Tag)。拼接标签值和此缓存块的索引,即可求得缓存块的内存地址。如果再加上块内偏移,就能得出任意一块数据的对应内存地址。

因此,在缓存大小不变的情况下,缓存块大小和缓存块总数成反比关系。下图中所示的缓存块来自一个数据总量为4KB、每个缓存块大小为16B的直接映射缓存,其标签长度为20比特()。


此外,每个缓存块还可对应若干标志位,包括有效位(valid bit)、脏位(dirty bit)、使用位(use bit)等。这些位在保证正确性、排除冲突、优化性能等方面起着重要作用。

运作流程

下面简要描述一个假想的直接映射缓存的工作流程。这个缓存共有四个缓存块,每个块16字节,即4个字,因此共有64字节存储空间。使用写回(Write back)策略以保证数据一致性。

CPU缓存的运作流程(注意内存左侧给出的地址是字地址而不是字节地址)

系统启动时,缓存内没有任何数据。之后,数据逐渐被载入或换出缓存。假设在此后某一时间点,缓存和内存布局如右图所示。此时,若处理器执行数据读取指令,控制逻辑依如下流程:

  1. (将地址由高至低划分为四个部分:标签、索引、块内偏移、字节偏移。其中块内偏移和字节偏移各占两位,后者在以下操作中不使用。)
  2. 用索引定位到相应的缓存块。
  3. 用标签尝试匹配该缓存块的对应标签值。如果存在这样的匹配,称为命中(Hit);否则称为未命中(Miss)。
  4. 如命中,用块内偏移将已定位缓存块内的特定数据段取出,送回处理器。
  5. 如未命中,先用此块地址(标签+索引)从内存读取数据并载入到当前缓存块,再用块内偏移将位于此块内的特定数据单元取出,送回处理器。这里要注意的是,(1)读入的数据会冲掉之前的内容。为保证数据一致性,必须先将数据块内的现有内容写回内存。(2)尽管处理器请求的只是一个字,缓存仍必须在读取的时候把整个数据块都填充满。(3)缓存的读取是按缓存块大小为边界对齐的。对于大小为16字节的缓存块,任何因为0x0000、或0x0001、或0x0002、或0x0003造成的未命中,都会导致位于内存0x0000—0x0003的全部四个字被读入块中。

在下图中,如此时处理器请求的地址在0x0020到0x0023之间,或在0x0004到0x0007之间,或在0x0528到0x052B之间,或在0x05EC到0x05EF之间,均会命中。其余地址则全部未命中。


而处理器执行数据写入指令时,控制逻辑依如下流程:

  1. 用索引定位到相应的缓存块。
  2. 用标签尝试匹配该缓存块的对应标签值。其结果为命中或未命中。
  3. 如命中,用块内偏移定位此块内的目标字。然后直接改写这个字。
  4. 如未命中,依系统设计不同可有两种处理策略,分别称为分配写(Write allocate)和非分配写(No-write allocate)。如果是分配写,则先如处理读未命中一样,将未命中数据读入缓存,然后再将数据写到被读入的字单元。如果是非分配写,则直接将数据写回内存

猜你喜欢

转载自blog.csdn.net/Kair_Wu/article/details/48469387
CUP
今日推荐