前言

了解下CPU和主存之间的读取关系,Cache Line如何读取的。

Cache

我们的程序都是运行在RAM之中的,RAM就是称为主存(main memory)。
当CPU寄存器要加载数据时,就要从主存中加载,一般CPU寄存器速度是1ns,主存速度是65ns,为了减少等待,这里就添加了缓存,即cache memory。
当CPU加载主存数据时,先从cache中查找,命中直接返回;未命中情况下,再从主存加载到cache,返回给CPU。

多级Cache

一般chache会引入多个。称之为L1 cache(第一级缓存),L2 cache,L3 cache,最后是主存。
image.png
在这其中L1 cache是CPU似有的,每个CPU有一个L1 cache;
一个CPU cluster内,所有的CPU共享一个L2 cache;
所有的cluster之间共享L3 cache,L3 cache通过总线和主存相连。
当CPU加载主存数据时,先从L1 cache中查找,命中直接返回;未命中时,则从L2 cache中查找,命中的话,数据返回给L1 cahce和CPU。L2 cache未命中,查找L3 cache同理。这种cache结构保证了数据不可能同时在多个chache中。

Cache Line

Cache Line可以理解为CPU cache的最小缓存单位,目前主流的CPU Cache的Cache Line大小都是64Bytes。就是说,CPU每次读取主存数据加载到cache时,都是从主存中一次性加载一个Cache Line(即64Bytes),各个CPU之前也是通过Cache Line进行数据交换的。

注:即使读取1个byte,cache也要从主存加载8字节填充到整个cache line。

Cache存放数据

有了cache,这时候需要加载主存数据到cache中。如何加载缓存就是主要的问题。一种可行的方式就是,将cache当做Hash数组,内存地址的Hash值当做数据的index,缓存对象的值就是数组的value。当读取一个地址时,先做hash计算,从cache中查找,找不到再加载。

Fully Associative

一种存在的方案,即每个数据可以缓存在任何一个的Cache Line中,那么这个cache就是Fully Associative。但是实际不行,查找数据时,又要遍历所有的cache了。

直接映射Cache

将cache大小(通常1M)按照cache line大小(通常64bytes)分成n条line,并加上编号。然后将主存(例如4G)按照n进行划分。这样每份内存(大概256K)对应一条cache line,就便于寻找数据了。缺点是效率不高。

N-Way Set Associative

原理是把一个缓存按照N个Cache Line作为一组(set),缓存按组划为等分。这样一个64位系统的内存地址在4MB二级缓存中就划成了三个部分(见下图),低位6个bit表示在Cache Line中的偏移量,中间12bit表示Cache组号(set index),剩余的高位46bit就是内存地址的唯一id。
image.png
将内存分成3个区间:
image.png
整体的Cache结构如下:
image.png
寻找方法:
valid通常一位,代表当前的cache line是否有效(该cache line不存在内存映射时,就是无效的)
set index决定了该单元应该被映射到哪个组,即给定一个内存地址可以唯一对应一个set,对于set内,只需要遍历16个元素就能确定对象是否在缓存中了。
image.png

参考