计算机组成原理:CPU Cache(高速缓存) | 您所在的位置:网站首页 › 高速缓存作用及其原理 › 计算机组成原理:CPU Cache(高速缓存) |
为什么需要CPU Cache
为了弥补CPU和内存之间的性能差异,以便于能够真实变得把CPU的性能提升利用起来,而不是让它在那里空转,我们在现代CPU中引入了高速缓存。 从CPU Cache被加入到现有的CPU里开始,内存中的指令、数据,会被加载到L1-L3 Cache中,而不是直接从CPU访问内存中取拿。 CPU从内存读取数据到CPU Cache的过程中,是一小块一小块来读取数据的,而不是按照单个数组元素来读取数据的。这样一小块一小块的数据,在CPU Cache里面,叫做Cache Line(缓存块) 在我们日常使用的 Intel 服务器或者 PC 里,Cache Line 的大小通常是 64 字节。 知道了为什么需要CPU Cache,接下来,我们就来看一看,CPU究竟是如何访问CPU Cache的,以及CPU Cache是如何组织数据的 Cache的数据结构和读取过程是怎么样的现代CPU进行数据读取的时候,无论数据是否已经存储在Cacha中,CPU时钟会首先访问Cache。只有当CPU在Cache中找不到数据的时候,才会去访问内容,并且将读取到的数据写入Cache中。当时间局部性原理其作用后,这个最近刚刚被访问的数据,会很快再次被访问。而Cache的访问速度远远快于内存,这样,CPU花在等待内存访问上的时间就大大变短了。 问题来了,CPU如何知道要访问的内存数据,存储在Cache的哪个位置呢?接下来,从最基本的直接映射 Cache(Direct Mapped Cache)起,了解整个 Cache 的数据结构和访问逻辑: CPU访问内存数据,是一小块一小块数据来读取的。对于读取内存中的数据,我们首先拿到的是数据所在内存块(block)的地址。而直接映射Cache采用的策略,就是确保任何一个内存块的地址,时钟映射到一个固定的CPU Cache地址(Cache Line)。而这个映射关系,通常用mod运算来实现。比如说,我们的主内存被分成0-31号这样的32个块。我们一共有8个缓存块。用户想要访问第21号内存块。如果21号内存块内容在缓存块中的话,它一定在5号缓存块(21 mode 8 = 5)中。![]() 总结一下,一个内存的访问地址,最终包括高位代表的组标记、低位代表的索引,以及在对应的 Data Block 中定位对应字的位置偏移量。 而内存地址对应到Cache里的数据结构,则多了一个有效位和对应的数据,由“索引+有效位+组标记+数据”组成。如果内存中的数据已经在CPU Cache里了,那一个内存地址的访问,就会经历下面4个步骤 根据内存地址的低位,计算在 Cache 中的索引;判断有效位,确认 Cache 中的数据是有效的;对比内存访问地址的高位,和 Cache 中的组标记,确认 Cache 中的数据就是我们要访 问的内存数据,从 Cache Line 中读取到对应的数据块(Data Block);根据内存地址的 Offset 位,从 Data Block 中,读取希望读取到的字。如果在 2、3 这两个步骤中,CPU发现,Cache中的数据并不是要访问的内存地址的数据,那CPU就会访问内存,并把对应的Block Data更新到Cache Line中,同时更新对应的有效位和组标记的数据。 可以看到:通过巧妙的将内存地址,拆分成“索引+组标记+偏移量”的方式,使得我们可以将很大的内存地址,映射到很小的CPU Cache地址里。 另外:除了直接映射 Cache 之外,我们常见的缓存放置策略还有全相连 Cache(Fully Associative Cache)、组相连 Cache(Set AssociativeCache)。 你确定你的数据更新了吗?CPU不仅要读数据,还需要写数据,问题是,CPU在写入数据的时候,怎么既不牺牲性能,又能保证数据的一致性呢? 我们现在用的 Intel CPU,通常都是多核的的。每一个 CPU 核里面,都有独立属于自己的L1、L2 的 Cache,然后再有多个 CPU 核共用的 L3 的 Cache、主内存。
最简单的一种写入策略,叫做写直到。在这个策略里,每一次数据都要写入到主内存里。 写入前,我们会先去判断数据是否已经在Cache里面了如果数据已经在Cache里面,我们就先把数据写入更新到Cache里面,再写入到主内存中如果数据不在Cache里面,我们就只更新主内存写直到这个策略很直观,但是问题也很明显,那就是这个策略很慢。无论数据是不是在Cache里面,我们都需要把数据写到主内存里面。 这个时候,我们就想了,既然我们去读数据也是默认从 Cache 里面加载,能否不用把所有的写入都同步到主内存里呢?只写入 CPU Cache 里面是不是可以? 当然是可以的。在 CPU Cache 的写入策略里,还有一种策略就叫作写回。这个策略里,我们不再是每次都把数据写入到主内存,而是只写到CPU Cache里。只有当CPU Cache里面的数据都要被“替换”的时候,我们才把数据写入到主内存里面去。 写回策略的过程是这样的: 如果发现我们要写入的数据,就在CPU Cache里面,那么我们就只是更新CPU Cache里面的数据同时,我们会标记CPU Cache里的这个Block是脏(Drity)的。所谓“脏”,就是指这个时候,我们的CPU Cache里面的这个Block的数据,和主内存是不一致的。如果我们发现,我们要写入的数据所对应的 Cache Block 里,放的是别的内存地址的数据,那么我们就要看一看,那个 Cache Block 里面的数据有没有被标记成脏的。 如果是脏的话,我们要先把这个 Cache Block 里面的数据,写入到主内存里面。然后,再把当前要写入的数据,写入到 Cache 里,同时把 Cache Block 标记成脏的。如果 Block 里面的数据没有被标记成脏的,那么我们直接把数据写入到 Cache 里面,然后再把 Cache Block 标记成脏的就好了。 在用了写回这个策略之后,我们在加载内存数据到 Cache 里面的时候,也要多出一步同步脏 Cache 的动作。如果加载内存里面的数据到 Cache 的时候,发现 Cache Block 里面有脏标记,我们也要先把 Cache Block 里的数据写回到主内存,才能加载数据覆盖掉Cache
|
CopyRight 2018-2019 实验室设备网 版权所有 |