如何提升 Cache 的性能
如何提升 Cache 的性能
1 Cache 的基本结构与原理
Cache 在存储层次结构中处于 CPU 和主存之间,因此,Cache 的性能对会对 CPU 的性能造成很大的影响,它通过程序的局部性原理,使得 CPU 更快地获取原来储存在主存中的数据,从而提升性能。
Cache 一般的结构如下:
上图展示的是一个 2路组相联 Cache 的结构,Cache 中的数据是以块为单位存储的,块的大小没有明确的限制,可以是几十、上百个字节等等。Cache 中除了数据字段,还包括了 tag 字段和 valid 字段,它们的安逸分别是:
-
数据字段(data):存放主存中的数据。
-
tag 字段:用于在 Cache 中寻找数据。
-
valid 字段:用于标识该数据是否是有效的。
Cache 的基本工作过程是:
- 首先,将主存地址进行划分 [ 主 存 地 址 ] = [ T a g I n d e x O f f s e t ] [主存地址]=[Tag\quad Index \quad Offset] [主存地址]=[TagIndexOffset],例如, 上图Cache 的结构为,4组,两路,块大小为4字节,则地址的低 l o g 2 ( 块 大 小 ) log_2(块大小) log2(块大小) 位用来表示 Offset ,地址中间的 l o g 2 ( 组 数 ) log_2(组数) log2(组数) 位表示 Index ,剩下的高位表示 Tag。
- 通过 Index 字段寻找到 Cache 中对应的组,再在该组中遍历每一项,先判断有效位(Valid)是否为1,若为1,则继续比较 Tag 若 Tag 一致,即找到对应的数据,随后,通过 Offset 将数据读出。
2 评估 Cache 的性能
下介绍两种评价 Cache 性能的方法:
- 平均访存时间
其定义如下:
平
均
访
存
时
间
=
(
1
−
失
效
率
)
×
命
中
时
间
+
失
效
率
×
(
命
中
时
间
+
失
效
开
销
)
=
命
中
时
间
+
失
效
率
×
失
效
开
销
平均访存时间=(1-失效率)\times 命中时间+失效率\times (命中时间+失效开销)=命中时间+失效率\times 失效开销
平均访存时间=(1−失效率)×命中时间+失效率×(命中时间+失效开销)=命中时间+失效率×失效开销
- CPU时间
C P U 时 间 = I C × ( C P I E X E C U T I O N + 失 效 率 × 平 均 访 存 次 数 × 失 效 开 销 ) × 时 钟 周 期 CPU时间=IC\times (CPI_{EXECUTION}+失效率\times 平均访存次数\times 失效开销)\times 时钟周期 CPU时间=IC×(CPIEXECUTION+失效率×平均访存次数×失效开销)×时钟周期
平 均 访 存 次 数 = 访 存 次 数 指 令 数 平均访存次数=\frac{访存次数}{指令数} 平均访存次数=指令数访存次数
通过以上的两个式子,我们可以发现,影响 Cache 性能的指标主要有这三项:命中时间、失效率、失效开销,接下来,就针对这三项指标,提出一些 Cache 的改进措施。
3 通过降低失效率来提升 Cache 性能
3.1 Cache 失效的原因有如下三种:
- 强制失效:就是指,CPU 第一次访问一个块时,该块还未被调入到 Cache 中,还存储在主存中,此时,必然会发生失效。而减少此类冲突的简单方法就是进行数据预取,即预先将数据取入 Cache。
- 容量失效:为了追求性能, Cache 的容量有限,不可避免地不能将程序需要的所有数据都缓存进入 Cache ,此时便会发生容量失效。一般可以哦通过增大 Cache 容量来缓解此类冲突。
- 冲突失效:这种失效发生在多个块映像到 Cache 的同一组时,这时,会发生一个块替换另一个块的情况,而 Cache 中还有其他的空间是空闲的,此时,当要访问被替换块时,就会发生失效,这就是冲突失效。一般可以通过增大相连度来缓解此类冲突。
3.2 通过适当调整块大小来降低失效率
在增加块大小时,一方面可以更好地利用程序的空间局部性,减少失效率,然而,在Cache 容量一定的情况下,增加块大小的同时,Cache 中存放的总的块数将会减少,这会增加冲突失效的发生,导致失效率增大。因此,需要做出合理的折中,通过调整块大小来降低失效率。
另一方面,块大小的选取还与主存的带宽、延迟有关系。例如,如果当前主存有高延迟、高带宽的性质,此时,块大小应该选取地大一些,因为在这种情况下,如果 Cache 发生失效,那么需要从主存读取数据,因为当前主存是高带宽和高延迟的,多读取一些字无疑是更加划算的。
3.3 通过编译器优化来降低失效率
在另一篇博客中有提到。
4 通过减少失效开销来提高 Cache 性能
4.1 运用写缓冲及写合并技术
当Cache 中有数据需要写入主存时,一般的做法是暂停指令执行的流水线,进行写主存的操作,而这个写主存操作所消耗的时间对于CPU 来说是巨大的开销,一般是上百个时钟周期。为了让 CPU 尽可能减少等待的时间,可以设置一个写缓冲结构:
这时,当Cache 中有数据需要写入主存时,CPU 将要写入的内容先写到写缓冲结构中,转而去做其他工作,这时写缓冲往主存写数据和 CPU 执行其他指令就可以并行执行了,这样便可以减少失效开销。
写缓冲的性能影响了失效开销,可以通过 写合并 技术来提高写缓冲的效率和利用率。
写合并的工作原理为,当写缓冲已经包含了其他块,这些块对应的地址将会逐一被检查,以确定即将写入主存的块的地址是否与写缓冲的某个块能匹配上,若匹配上,则将这两个块进行合并。事实上,一般而言,连续多字一起写入主存往往比将各字逐一写入主存要高效一些。
4.2 非阻塞Cache 技术
这是一种复杂度较高,但被广泛采用的技术。基本思想就是在 Cache 在处理数据失效时继续服务其他访问,这样就可以重叠多个 Cache 访问,从而提高 CPU 的性能。
4.3 其它
还有诸如请求字优先技术、多级Cache技术都可以在一定条件下减少失效开销。
5 通过降低命中时间来提升 Cache 性能
5.1 使用容量小、结构简单的 Cache
这就是多级 Cache 设立的第一级 Cache 所遵循的基本原则。
5.2 利用Trace Cache技术
在另一篇博客中有介绍。