【笔记】存储器层次结构

编程入门 行业动态 更新时间:2024-10-24 22:29:22

【笔记】<a href=https://www.elefans.com/category/jswz/34/1766391.html style=存储器层次结构"/>

【笔记】存储器层次结构

参考书籍:《深入理解计算机系统》、《计算机体系结构:量化研究方法》

基本概念

SRAM

静态RAM将每个位存储在一个双稳态存储器单元里,只要有电,它就会永远地保持它的值。SRAM比DRAM更快,但也更贵,可以作为高速缓存存储器。

DRAM

动态RAM将每个位存储为对一个电容的充电,它的存储单元对干扰非常敏感。当电容的电压被扰乱之后,它就永远不会恢复了。

漏电会使得DRAM在很短的时间失去电荷,所以内存系统必须周期性地通过读出,然后重写来刷新内存每一位。

DIMM

DRAM芯片封装在内存模块中,它插到主板的扩展槽上。双列直插内存模块(Dual Inline Memory Module, DIMM)以64位为块传送数据到内存控制器和从内存控制器中传出数据。

SDRAM

同步DRAM用于驱动内存控制器相同的外部时钟信号的上升沿来代替许多这样的控制信号,这使得它能够比那些异步的存储器更快地输出它的超单元的内容。

DDR

双倍数据速率同步DRAM(DDR SDRAM)是对SDRAM的一种增强,它通过使用两个时钟沿作为控制信号,从而使DRAM的速度翻倍。

非易失存储器

如果断电,DRAM和SRAM或丢失它们的信息,而非易失性存储器即使是关电后,仍然保存着它们的信息。虽然非易失性存储器有的类型可以读也可以写,但整体上都被称为只读存储器(ROM)。ROM是根据它们能够被重编程的次数和对它们进行重编程所用的机制来区分的。

闪存

闪存是一类非易失性存储器,它是基于EEPROM(电子可擦写可编程ROM)的。

USB

通用串行总线(Universal Serial Bus)控制器是一个连接到USB总线的设备中转机构,USB总线是一个广泛使用的标准,连接各种外围I/O设备。

LRU

LRU是一种缓存替换策略,它选择替换掉最后被访问的时间距现在最远的块。

抖动

高速缓存反复地加载和驱逐相同的高速缓存。

关键点

SSD读写原理

固态硬盘(Solid State Disk)是一种基于闪存的存储技术,它封装插到I/O总线上标准硬盘插槽(通常是USB或SATA)中,处理来自CPU的读写逻辑磁盘块的请求。一个SSD封装由一个或多个闪存芯片和闪存翻译层组成。

一个闪存由B个块的序列组成,每个块由P页组成。数据是以页为单位读写的,只有在一页所属的整个块被擦除后,才能写这一页。不过,一旦一个块被擦除后,块中每一个页都可以不需要再进行擦除就写一次。

随机写很慢,有两个原因:

  • 擦除块需要相对较长的时间,比访问页所需时间要高一个数量级;
  • 如果写操作试图修改一个包含已经有数据的页,那么这个块中所有带有用数据的页都必须被复制到一个新块,然后才能进行对该页进行修改。

SSD与旋转磁盘对比:

  • SSD由半导体存储器构成,没有移动的部件,因而随机访问速度比旋转磁盘要快,能耗更低,同时也更结实;
  • 因为反复写之后,闪存块会磨损,所以SSD 也更容易磨损。

时间局部性和空间局部性

局部性原理:一个编写良好的计算机程序倾向于引用邻近于其他最近引用过的数据项的数据项,或者最近引用过的数据项本身。

  • 在一个具有良好时间局部性的程序中,被引用过一次的内存位置很可能在不远的将来再被多次引用;
  • 在一个具有良好空间局部性的程序中,如果一个内存位置被引用了一次,那么程序很可能在不远的将来引用附近的一个内存位置。

一般而言,有良好局部性的程序比局部性差的程序运行得更快。

优化缓存性能

编译器优化

循环交换

一些程序存在嵌套循环,它们会以非连续顺序访问存储器中的数据,只要交换一下这些循环的嵌套顺序,就可能使程序代码按照数据的存储顺序来访问它们。如果缓存中无法容纳这些数组,那么这一技术可以通过提高空间局域性来减少缺失。通过重新排序,可以使缓存块中的数据被替换之前,得到最大限度的充分利用。

/* 优化之前 */
for (j = 0; j < 100; j++)for (i = 0; i < 5000; i++)x[i][j] = 2 * x[i][j];
/* 优化之后 */
for (i = 0; i < 5000; i++)for (j = 0; j < 100; j++)x[i][j] = 2 * x[i][j];
分块

这一优化方法通过提高时间局域性来减少缺失。这一次还是要处理多个数组,有的数组是按行来访问的,有的是按列来访问的。由于在每个循环迭代中都用到了行和列,所以按行或按列来存储数组并不能解决问题(按行存储称为行主序,按列存储称为列主序)。

分块算法不是对一个数组的整行或整列进行操作,而是对其子矩阵进行操作,其目的是在缓存中载入的数据被替换之前,在最大限度上利用它。

/* 优化之前 */
for (i = 0; i < N; i++) {for (j = 0; j < N; j++) {r = 0;for (k = 0; k < N; k++) {r = r + y[i][k] * z[k][j];}x[i][j] = r;}
}

容量缺失的数目显然取决于N和缓存的大小,如果缓存能容纳这三个N×N矩阵,只要没有缓存冲突,就一切正常。如果缓存可以容纳一个N×N矩阵和包含N个元素的一行,则至少y的第i行和z可以停留在缓存中。如果缓存容量更小,那可能对于xz都会发生缺失。

为了确保正在访问的元素能够放在缓存中,我们对原来的代码进行修改:改为计算一个大小为B×B的子矩阵。两个内层循环现在以大小为B(被称为分块因子)的步长进行计算,而不是以x(要提前把里面的元素初始化为0)和z的完整长度为步长。

/* 优化之后 */
for (jj = 0; jj < N; jj += B) {for (kk = 0; kk < N; kk += B) {for (i = 0; i < N; i++) {for (j = jj; j < min(jj + B, N); j++) {r = 0;for (k = kk; k < min(kk + B, N); k++) {r = r + y[i][k] * z[k][j];}x[i][j] = x[i][j] + r;}}}
}

用编译器控制预取

作为硬件预取的替代方法,可以在处理器需要某一数据之前,由编译器插入请求该数据的预取指令。共有以下两种预取:

  • 寄存器预取将数据值载入到一个寄存器中;
  • 缓存预取仅将数据载入到缓存中。

更多推荐

【笔记】存储器层次结构

本文发布于:2024-02-12 16:56:48,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1688646.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:存储器   层次   结构   笔记

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!