计算机体系结构 第7章 存储系统(3)

   日期:2024-12-27    作者:jogmu 移动:http://ljhr2012.riyuangf.com/mobile/quote/72928.html

总共介绍种降低不命中率的方法

7.3.1 三种类型的不命中

按照产生不命中的原因,可以把不命中分为三种类型

强制性不命中(Compulsory miss)

  • 当第一次访问一个块时,该块不在Cache中,需从下一级存储器中调入Cache,这就是强制性不命中。 (冷启动不命中,首次访问不命中

容量不命中(Capacity miss )

  • 如果程序执行时所需的块不能全部调入Cache中,则发生容量缺失,随后再被调入。这种不命中称为容量不命中。

冲突不命中(Conflict miss)

  • 在组相联或直接映象Cache中,若太多的块映象到同一组(块)中,则会出现该组中某个块被别的块替换(即使别的组或块有空闲位置),然后又被重新访问的情况。这就是发生了冲突不命中。

经过测试数据可以得出以下结论

  • 相联度越高,冲突不命中就越少
  • 强制性不命中和容量不命中不受相联度的影响
  • 强制性不命中不受Cache容量的影响,但容量不命中却随着容量的增加而减少。

减少三种不命中的方法

  • 强制性不命中:增加块大小,预取(本身很少
  • 容量不命中:增加容量 (抖动现象
  • 冲突不命中:提高相联度(理想情况:全相联

许多降低不命中率的方法会增加命中时间或不命中开销

7.3.2 增加Cache块大小

不命中率与块大小的关系

  • 对于给定的Cache容量,当块大小增加时,不命中率开始是下降,后来反而上升了(先下降后上升)。
  • Cache容量越大,使不命中率达到最低的块大小就越大。

原因是增加块大小产生了双重作用

  • 增强了空间局部性减少了强制性不命中
  • 由于增加块大小会减少Cache中块的数目,所以有可能会增加冲突不命中

值得注意的是:增加块大小会。需要在其降低不命中率与增加不命中开销直接进行权衡。

7.3.3 增加Cache的容量

这是降低Cache不命中率的办法(这种方法在中用得比较多

缺点

  • 增加成本
  • 可能增加命中时间

7.3.4 提高相联度

采用相联度超过8的方案的实际意义不大。(8路组相联的作用已经与全相联相差不大

2:1 Cache经验规则

  • 容量为的直接映象Cache的不命中率和容量为的两路组相联Cache的不命中率差不多相同。

注意:提高相联度是以增加为代价。

7.3.5 伪相联 Cache (列相联 Cache )

这一方法结合了多路组相联的低不命中率和直接映象的命中速度

优点缺点直接映像命中时间小不命中率高组相联映像不命中率低命中时间大

伪相联Cache的优点

  • 命中时间小
  • 不命中率低

基本思想及工作原理

  • 在逻辑上把直接映象Cache的空间上下平分为两个区。对于任何一次访问,伪相联Cache先按直接映象Cache的方式去处理(快速命中)。
  • 若命中,则其访问过程与直接映象Cache的情况一样。
  • 若不命中,则再到另一区相应的位置去查找。若找到,则发生了伪命中,否则就只好访问下一级存储器。

存在的问题

  • 如果直接映象Cache的许多快速命中,在伪相联Cache中变为慢速命中,则这种方法降低整体性能。需要指出哪一个块是快速的最重要。

  • 解决方法:出现伪命中时把最近访问过的块发在第一位置(根据程序的局部性原理)。

缺点

  • 多种命中时间,使得

7.3.6 硬件预取

指令和数据都可以在处理器提出访问请求之前预取

预取内容既可放入Cache,也可放在外缓冲器中(访问速度比主存快)。

指令预取通常由Cache之外的硬件完成

预取效果——Joppi的研究结果

  1. 指令预取 (4KB,直接映象Cache,块大小=16字节)

    • 个块的指令流缓冲器: 捕获的不命中
    • 个块的指令流缓冲器: 捕获
    • 个块的指令流缓冲器:捕获
  2. 数据预取 (4KB,直接映象Cache)

    • 个数据流缓冲器:捕获的不命中
    • 还可以采用多个数据流缓冲器

结论预取应利用存储器的空闲带宽,不能影响对正常不命中的处理,否则可能会降低性能。

7.3.7 编译器控制的预取

在编译时加入预取指令,在数据被用到之前发出预取请求。

指令和数据在被用到之前就取到寄存器或者Cache中

按照预取数据所放的位置,可把预取分为两种类型

  • 寄存器预取:把数据取到寄存器中。
  • Cache预取:只将数据取到Cache中。

按照预取的处理方式不同,可把预取分为

  • 故障性预取:在预取时,若出现虚地址故障或违反保护权限,就会发生异常。

  • 非故障性预取:在遇到这种情况时则不会发生异常,因为这时它会放弃预取,转变为空操作。

最有效的预取,既不会改变指令和数据之间的各种逻辑关系或存储单元的内容,也不会造成虚拟存储器故障。假定后面讨论的Cache预取都是非故障性的,也叫做非绑定预取。

⚠️在预取数据的同时,处理器应能继续执行,预取才有意义。

  • 要求Cache在等待预取数据返回的同时,还能继续提供指令和数据,这种Cache称为非阻塞Cache

编译器控制预取的目的

  • 使执行指令和读取数据能重叠执行。

循环是预取优化的主要对象

  • 不命中开销小时:循环体展开次
  • 不命中开销大时:循环体展开许多次

由于每次预取需要花费一条指令的开销

  • 需要保证这种开销不超过预取所带来的收益
  • 编译器可以通过把重点放在那些可能会导致不命中的访问上,使程序避免不必要的预取,从而较大程度地减少平均访存时间。

7.3.8 编译器优化

主要用在减少指令不命中减少数据不命中两方面

基本思想:通过对软件进行优化来降低不命中率。

特色:无需对硬件做任何改动

编译优化技术

  • 程序代码和数据重组

  • 数组合并

    将本来相互独立的多个数组合并成为一个复合数组,以提高访问它们的局部性。

  • 内外循环交换

  • 循环融合

    将若干个独立的循环融合为单个的循环。这些循环访问同样的数组,对相同的数据作不同的运算。这样能使得读入Cache的数据在被替换出去之前,能得到反复的使用 。

  • 分块

  1. 程序代码和数据重组
  • 可以重新组织程序而不影响程序的正确性
  • 例如,把一个程序中的过程重新排序,就可能会减少冲突不命中,从而降低指令不命中率。
  • McFarling研究了如何使用配置文件(profile)来进行这种优化。
  • 提高大Cache块的效率:把基本块对齐,使得程序的入口点与Cache块的起始位置对齐,就可以减少顺序代码执行时所发生的Cache不命中的可能性。

对分支指令的优化

如果编译器知道一个分支指令很可能会成功转移,那么它就可以通过以下两步来改善空间局部性

  • 将转移目标处的基本块和紧跟着该分支指令后的基本块进行对调
  • 把该分支指令换为操作语义相反的分支指令。
  1. 内外循环交换

有些程序的嵌套循环中,程序不是按照数据在存储器中存储的顺序进行访问的,简单的交换循环的嵌套关系,就能使程序按数据在存储器中存储的顺序进行访问

举例

  • 修改前 (大块)空间局部性较差
 
  • 修改后(可访问同一块中各个元素,在访问下一个块。
 
  1. 分块

通过提高时间局部性来减少不命中。

例如,把对数组的整行或整列访问改为按块进行。

举例

  • 矩阵乘法(修改前
  • 计算过程(不命中次数
 
  • 矩阵乘法(修改后
  • 计算过程 (不命中次数:)
 

分块技术的优点

  • 有助于寄存器分配
  • 可以把load和store操作的次数变成最小。

7.3.9 “牺牲” Cache

一种能减少冲突不命中次数而又不影响时钟频率的方法。

容量小,采用命中率较高的全相联映像,而且仅在替换时发生作用

基本思想

  • 在Cache和它从下一级存储器调数据的通路之间设置一个,称为“牺牲”Cache(Victim Cache)。用于存放被替换出去的块(称为牺牲者),以备重用。

工作过程

  • 每当发生不命中时,在访问下一级存储器之前,先检查“牺牲”Cache中是否有所需要的块。
  • 如果有,就将该块与Cache中的某个块做交换,把所需的块从“牺牲”Cache调入Cache。

7.3.10 降低Cache不命中率技术总结


特别提示:本信息由相关用户自行提供,真实性未证实,仅供参考。请谨慎采用,风险自负。


举报收藏 0评论 0
0相关评论
相关最新动态
推荐最新动态
点击排行
{
网站首页  |  关于我们  |  联系方式  |  使用协议  |  隐私政策  |  版权隐私  |  网站地图  |  排名推广  |  广告服务  |  积分换礼  |  网站留言  |  RSS订阅  |  违规举报  |  鄂ICP备2020018471号