这两天读了一篇:《让MySQL高效的N个习惯》,里面提到了L1,L2 Cache,那么好吧,各位知道Cache的含义么?
计算机中储存的构成
熟悉计算机系统的人都知道,存储器是分层次的,离CPU越近的存储器,速度越快,每字节的成本越高,同时容量也因此越小,所谓近水楼台先得月,金字塔尖儿的自然就那么几个。其中,寄存器速度最快,离CPU最近,成本最高,所以个数容量有限,其次是高速缓存(缓存也是分级,有L1,L2等缓存),再次是主存(普通内存),再次是本地磁盘。
下图列出了不同储存区域的平均访问时间:
寄存器可以在一个时钟周期内访问,其次是高速缓存,可以在几个时钟周期内访问,普通内存可以在几十个或几百个时钟周期内访问。储存器的是按照严格的等级制度来划分的,如果你要search某个东西,寄存器没有,则从缓存中取,缓存中没有,则从内存中取到缓存,如果内存中没有,则先从磁盘读入内存,再读入缓存,再读入寄存器。一级级的双向进行,不可僭越。
Cache结构组成
cache结构分成多个组,每个组分成多个行,linesize是cache的基本单位,有点表格的感觉。从主存向cache迁移数据都是按照linesize为单位替换的(说白了就是行)。比如linesize为32Byte,那么迁移必须一次迁移32Byte到cache。(固定迁移替换单位是有深层次原因的)
所谓8路组相连( 8-way set associative)的含义是指,每个组里面有8个行。
我们知道,cache的容量要远远小于主存,主存和cache肯定不是一一对应的,那么主存中的地址和cache的映射关系是怎样的呢?
拿到一个地址,首先是映射到一个组里面去。如何映射?取内存地址的中间几位来映射。
举例来说,data cache: 32-KB, 8-way set associative, 64-byte line size
Cache总大小为32KB,8路组相连(每组有8个line),每个line的大小linesize为64Byte,OK,我们可以很轻易的算出一共有32K/8/64=64 个组。
对于32位的内存地址,每个line有2^6 = 64Byte,即line有6位,所以地址的【0,5】区分line中的那个字节。一共有64个组,所以组区分要再占去6位,我们取内存地址中间6为来hash查找地址属于那个组。即内存地址的【6,11】位来确定属于64组的哪一个组。组确定了之后,剩下的【12,31】的内存地址与组中8个line挨个比对,如果【12,31】为与某个line一致,并且这个line为有效,那么缓存命中。
上面讲述的就是cache到内存的映射过程,我感觉不能再清楚了。
Cache分类
那么最后,讲讲cache分类
1 直接映射高速缓存,这个简单,即每个组只有一个line,选中组之后不需要和组中的每个line比对, 因为只有一个line。所以它的缺点也暴露的很明显,就是容量太小。
2 组相联高速缓存,这个就是我们上面介绍的cache。 M个组,每个组N个line。
3 全相联高速缓存,这个简单,只有一个组,就是全相联。不用hash来确定组,直接挨个顺序比对高位地址,来确定是否命中。可以想见这种方式不适合大的缓存。想想看,如果4M 的大缓存 linesize为32Byte,采用全相联的话,就意味着4*1024*1024/32 = 128K 个line挨个比较,来确定是否命中,这是多要命的事情。高速缓存立马成了低速缓存了。
Cache的描述
描述一个cache需要以下参数 :
1 cache分级,L1 cache, L2 cache, L3 cache,级别越低,离cpu越近
2 cache的容量
3 cache的linesize
4 cache 每组的行个数.
组的个数完全可以根据上面的参数计算出来,所以没有列出来.
Intel手册中用这样的句子来描述cache:
8-MB L3 Cache, 16-way set associative, 64-byte line size