存储器层次结构——基于存储器的程序优化

局部性原理

一个编写良好的计算机程序常常具有良好的局部性,它们倾向于引用邻近于其他最近引用过的数据项的数据项,或者最近引用过的数据项本身。局部性通常有两种不同的形式:

  • 时间局部性:被引用过一次的存储器位置很可能在不远的将来再被多次引用。
  • 空间局部性:如果一个存储器位置被引用了一次,那么程序很可能在不远的将来引用附近的一个存储器位置。

下面来看个局部性的代码示例:
这里写图片描述
变量sum在每此循环中被引用一次,因此具有良好的时间局部性。变量v的元素被顺序读取,具有良好的空间局部性。
像这种顺序访问向量每一个元素的函数,我们称为步长为1的引用模式,也叫顺序引用模式。一个连续向量中,每隔k个元素进行访问,就称为步长为k的引用模式。随着步长增长,空间局部性下降。
这里写图片描述
这里写图片描述

那么,为什么局部性会对性能产生影响呢,因为在存储器的层次结构中使用了缓存。

缓存

再次祭出这张图:
这里写图片描述
存储器层次结构的中心思想是,对于每个k,位于k层的更快更小的存储设备作为位于k+1层的更大更慢的存储设备的缓存。换句话说,层次结构中的每一层都缓存来自较低一层的数据对象。

  • 缓存命中:当程序需要第k+1层的某个数据对象d时,它首先在当前存储在第k层的一个块中查找d。如果d刚好缓存在第k层中,那么就是我们所说的缓存命中。
  • 缓存不命中:如果第k层中没有缓存数据对象d,那么就是我们所说的缓存不命中。当发生缓存不命中时,第k层的缓存从第k+1层缓存中取出包含d的那个块,之后,程序就能像前面一样从第k层读出d了。
    缓存不命中有以下几种:
    • 冷不命中:第k层的缓存是空的时候,那么对任何数据对象的访问都会不命中。通常是短暂的事件。
    • 冲突不命中:因为多个k+1层的块会映射到k层的同一个缓存块。当我们交替请求两个映射相同的块时,会导致每次都不命中。
    • 容量不命中:当一个集合太大,工作集超过了缓存的大小时,会导致容量不命中。
  • 缓存管理
    在每一层上,某种形式的逻辑必须管理缓存。某个东西要将缓存划分成块,在不同的层之间传送块,判定是命中还是不命中,并处理它们。管理缓存的逻辑可以是硬件、软件,或是两者的结合。
    这里写图片描述

接下来我们以高速缓存为例来了解下缓存的工作原理。

高速缓存存储器

首先来看下通用的高速缓存存储器结构:
这里写图片描述
地址结构划分:
这里写图片描述

以下是对各参数的说明:
这里写图片描述

  • 读数据
    当我们请求一个地址数据的时候,分为三步,将地址按照上面的结构进行拆分:

    • 组选择:根据组索引确定地址映射在哪一组。
    • 行匹配:根据标记找到所在行。若标记不匹配或有效位未设置则缓存不命中。
    • 字抽取:根据块偏移找到所需数据块的位置。

    若缓存不命中,则从存储器层次结构的下一层取出被请求的块,然后将新的块存储在组索引指示的组中的一个高速缓存行。

  • 写数据

    • 写命中:要写的字已经缓存了。这时先在缓存中更新写内容。
      • 直写:缓存中更新完之后,直接更新低一层的存储器。
      • 写回:缓存中更新完之后,不直接更新,等到替换算法要驱逐更新过的块(一个块可能包含多个字)时,才把它更新到低一层的存储器。因为局部性原理,这种方式能够减少总线流量。
    • 写不命中:要写的字没有缓存。
      • 写分配:加载相应的低一层中的块到高速缓存中,然后更新这个高速缓存块。
      • 非写分配:避开高速缓存,直接把这个字写到更低一层中。

    在编写程序时,建议在心里采用一个使用写回和写分配的高速缓存的模型。

在平时编写程序时,根据缓存原理,意识到时间局部性与空间局部性,有助于我们编写更高效的代码。而根据这种思想,也可以构建更高效的处理结构。

<script type="text/javascript"> $(function () { $('pre.prettyprint code').each(function () { var lines = $(this).text().split('\n').length; var $numbering = $('<ul/>').addClass('pre-numbering').hide(); $(this).addClass('has-numbering').parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($('<li/>').text(i)); }; $numbering.fadeIn(1700); }); }); </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值