高速缓存
高速缓存
程序访问的局部性
最早期的计算机,在执行一段程序时,都是把硬盘中的数据加载到内存,然后
人们发现的这种规律被称为程序访问的局部性。程序访问的局部性包含
- 时间局部性:某个内存单元在较短时间内很可能被再次访问
- 空间局部性:某个内存单元被访问后相邻的内存单元较短时间内很可能被访问
出现这种情况的原因很简单,因为程序是指令和数据组成的,指令在内存中按顺序存放且地址连续,如果运行一段循环程序或调用一个方法,又或者再程序中遍历一个数组,都有可能符合上面提到的局部性原理。那既然在执行程序时,内存的某些单元很可能会经常的访问或写入,那可否在
事实证明利用这种方式,程序的运行效率会提高
缓存详解
缓存是
缓存由镜像主内存的小块组成。这些块的大小称为行大小,通常为
在正常操作期间,处理器会不断要求高速缓存检查高速缓存中是否存储了特定的地址,因此高速缓存需要某种方法来非常快速地查找其是否存在有效行。如果可以将给定地址缓存在缓存中的任何位置,则每次进行引用以确定命中或未命中时都需要搜索每个缓存行。为了保持快速搜索,这是在高速缓存硬件中并行完成的,但是对于合理大小的高速缓存而言,搜索每个条目通常过于昂贵。因此,可以通过限制特定地址必须驻留的位置来简化缓存。这是一个权衡;高速缓存显然比系统内存小得多,因此某些地址必须别名。如果两个彼此互为别名的地址一直在不断更新,则它们将争用缓存行。
-
直接映射的缓存(Direct mapped caches)将允许缓存行仅存在于缓存中的单个条目中。这是最简单的在硬件中实现的方法,由于两个阴影地址必须共享同一条缓存行,因此无法避免混淆现象。
-
完全关联高速缓存(Fully Associative caches)将允许高速缓存行存在于高速缓存的任何条目中。由于可以使用任何条目,因此可以避免别名问题。但是在硬件中实现非常昂贵,因为必须同时查找每个可能的位置以确定值是否在缓存中。
-
集合关联缓存(Set Associative caches)是直接关联和完全关联缓存的混合,并且允许特定的缓存值存在于缓存内的某些行子集中。高速缓存被划分为偶数部分,称为方式,并且可以以任何方式定位特定地址。因此,
n 路集关联缓存将允许在行大小为set n 的总块mod n 中的任何条目中存在一条缓存行。上图中“缓存关联性”显示了一个示例的8 元素,4 路集关联缓存。在这种情况下,这两个地址具有四个可能的位置,这意味着在查找时仅必须搜索一半的缓存。方式越多,可能的位置就越多,混淆现象就越少,从而导致总体上更好的性能。
一旦缓存已满,处理器就需要清除一行来为新行腾出空间,处理器可以通过多种算法选择逐出哪条线。例如,最近最少使用(LRU)是一种算法,其中丢弃最旧的未使用的行以为新行腾出空间。当仅从高速缓存中读取数据时,无需确保与主内存的一致性。但是,当处理器开始写入高速缓存行时,它需要就如何更新底层主内存做出一些决定。
-
直写式高速缓存(Write-through)将在处理器更新高速缓存时将更改直接写入主系统内存。这是较慢的,因为如我们所见,写入主存储器的过程较慢。
-
回写缓存(Write-back)会将更改延迟写入
RAM ,直到绝对必要为止。明显的优点是,写入缓存条目时需要较少的主存储器访问。已写入但未提交给内存的缓存行称为脏行。缺点是,当退出缓存条目时,它可能需要两次内存访问(一次写入脏数据主内存,另一次加载新数据) 。
如果一个条目同时存在于较高级别和较低级别的高速缓存中,则我们说较高级别的高速缓存是
缓存寻址
到目前为止,我们还没有讨论过缓存如何确定给定地址是否驻留在缓存中。显然,高速缓存必须保留当前驻留在高速缓存行中的数据的目录。缓存目录和数据可能位于同一处理器上,但也可能是分开的,例如在具有核心
需要并行检查标签以降低等待时间。更多的标记位(即,较少的设置关联性)需要更复杂的硬件来实现。另外,更多的集合关联性意味着更少的标签,但是处理器现在需要硬件来多路复用许多集合的输出,这也可能增加延迟。
为了快速确定地址是否位于缓存中,将其分为三个部分:标签,索引和偏移量。偏移位取决于高速缓存的行大小。例如,一个
现在,考虑相同的
当存在多种方式时,此检查必须在每种方式中并行进行,然后将其结果传递到多路复用器,该多路复用器输出最终的命中或未命中结果。如上所述,高速缓存的关联性越高,索引所需的位越少,而标记位则越多