我的编程空间,编程开发者的网络收藏夹
学习永远不晚

存储器的层次结构

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

存储器的层次结构

存储技术

我们在买电脑时都会关注内存、处理器、硬盘等部件的性能,都想内存尽可能大,硬盘最好是固态的。

不知道你有没有遇到过自己写了大半天的文档,因为不小心突然关机了,自己辛苦忙活了几个小时的成果又得重写的情况。可是你是否想过为什么关机了就会丢失这些信息呢?为什么硬盘上的文件没有丢?

会丢的那部分信息肯定是和电有关系的,不然也不会一断电就丢信息。内存就是这样的部件,更专业一点的称呼是随机访问存储器。

随机访问存储器(RAM)分静态和动态的两种,静态 RAM 是将信息存储在一个双稳态的存储单元里。什么叫双稳态呢?就是只有两种稳定的状态,虽然也有其它状态,但即使细微的扰动,也会让它立马进入一个稳定的状态。

动态 RAM 使用的是电容来存储信息,学过物理的都知道电容这个概念,它很容易就会漏电,使得动态 RAM 单元在 10~100 ms 时间内就会丢失电荷(信息),但是不要忘记,计算机的运行时间是以纳秒计算的,1 GHz 的处理器的时钟周期就是 1 ns,更何况现在的处理器都不止 1 GHz,所以 ms 相对于纳秒来说是很长的,计算机不用担心会丢失信息。

动态 RAM 芯片就封装在内存模块中,比内存更大的存储部件是磁盘,发现自己在旧文你真的了解硬盘吗?对磁盘总结的已经不错了,就直接过渡到局部性上面去了吧。

局部性

局部性通常有两种不同的形式:时间局部性和空间局部性。在一个具有良好时间局部性的程序中,被引用过一次的内存位置很可能在不远的将来会再被多次引用;同样在一个具有良好空间局部性的程序中,如果一个内存被引用了一次,那么程序很可能在不远的将来引用附近的一个内存位置。

不要小看局部性,局部性好的程序会比局部性差的程序运行的更快,要往高级程序员走,这是肯定需要了解的。我们选择把一些常用的文件从网盘下下来,利用的就是时间局部性。

下面这段代码,再简单不过,我们仅观察一下其中的v向量,向量v的元素是一个接一个被读取的,即按照存储在内存中的顺序被读取的,所以它有很好的空间局部性;但是每个元素都只被访问一次,就使得时间局部性很差了。实际上对于循环体中的每个变量,这个函数要么具有好的空间局部性,要么具有好的时间局部性。

int sumvec(int v[N]){
    int i, sum = 0;
    for(i = 0; i < N; i++){
        sum += v[i];
    }
    return sum;
}

像上面的代码,每隔 1 个元素进行访问,称之为步长为 1 的引用模式。一般而言,随着步长的增加,空间局部性下降。

当然,不仅数据引用有局部性,取指令也有局部性。比如for循环,循环体中的指令是按顺序执行的,并且会被执行多次,所以它有良好的空间局部性和时间局部性。

高速缓存

不同存储技术的访问时间差异很大,而我们想要的是又快又大的体验,然而这又是违背机械原理的。为了让程序运行的更快,计算机设计者在不同层级之间加了缓存,比如在 CPU 与内存之间加了高速缓存,而内存又作为磁盘的缓存,本地磁盘又是 Web 服务器的缓存。多次访问一个网页,会发现有一些网络请求的状态码是 300,这就是从本地缓存读取的。

如下图所示,高速缓存通常被组织为下面的形式,计算机需要从具体的地址去拿指令或者数据,而这个地址也被切分为不同的部分,可以直接映射到缓存上去。看下面详细的介绍应该更容易理解。

存储器的层次结构

直接映射高速缓存每个组只有一行。高速缓存确定一个请求是否命中,然后抽取出被请求的字的过程分为:组选择行匹配字抽取三步。

比如当 CPU 执行一条读内存字w的指令,首先从w地址中间抽取出s个组索引位,映射到对应的组,然后通过t位标记确定是否有字w的一个副本存储在该组中;最后使用b位的块偏移确定所需要的字块是从哪里开始的。

存储器的层次结构

上面这个图,还有下面这个表,对应着看,由于能力有限,感觉怎么都讲不好,多盯着一会儿,应该就会获得一种豁然开朗之感。

存储器的层次结构

直接映射高速缓存造成冲突不命中的原因在于每个组只有一行,组相联高速缓存放松了这一限制,每个组都保存多于一行的高速缓存行,所以在组选择完成之后,需要遍历对应组中的行进行行匹配。

存储器的层次结构

当然,我们可以把每个组中的缓存行数继续扩大,即全相联高速缓存,所有的缓存行都在一个组,它总共只有一个组。因此对地址的划分就不需要组索引了,如下图所示。

存储器的层次结构

编写缓存友好的代码
float dotprod(float x[8], float y[8]){
    float sum = 0.0;
    int i;
    for(i = 0; i < 8; i++){
        sum += x[i] * y[i];
    }
    return sum;
}

这段函数很简介,就是计算两个向量点积的函数,而且对于xy来说,这个函数具有很好的空间局部性,如果使用直接映射高速缓存,那它的缓存命中率并不高。

存储器的层次结构

从表中就能看到,每次对xy的引用都会导致冲突不命中,因为我们在xy的块之间抖动,即高速缓存反复的加载替换相同的高速缓存块组。

我们只需要做一个小小的改动,就能让命中率大大提高,即让程序运行的更快。这个改动就是把float x[8]改为floatx[12],改动后的索引映射就变成下面那样了,非常的友好。

存储器的层次结构

再来看一个多维数组,函数的功能是对所有元素求和,两种不同的写法。

// 第一种
int sumarrayrows(int a[M][N]){
    int i, j, sum = 0;
    for(i = 0; i < M; i++){
        for(j = 0; j < N; j++){
            sum += a[i][j];
        }
    }
    return sum;
}

// 第二种
int sumarrayrows(int a[M][N]){
    int i, j, sum = 0;
    for(j = 0; j < M; j++){
        for(i = 0; i < N; i++){
            sum += a[i][j];
        }
    }
    return sum;
}

从编程语言角度来看,两种写法的效果是一样的, 都是求数组所有元素的和,但是深入分析就会发现,第一种写法会比第二种运行的更快,因为第二种写法一次缓存命中都不会发生,而第一种写法会有 24 次缓存命中,所以第一比第二种运行更快是必然的结果,第一种和第二种的缓存命中模式分别如下所示(粗体表示不命中)。

存储器的层次结构

存储器的层次结构

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

存储器的层次结构

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

存储器的层次结构

存储技术我们在买电脑时都会关注内存、处理器、硬盘等部件的性能,都想内存尽可能大,硬盘最好是固态的。不知道你有没有遇到过自己写了大半天的文档,因为不小心突然关机了,自己辛苦忙活了几个小时的成果又得重写的情况。可是你是否想过为什么关机了就会丢失
2023-06-04

Mysql存储结构

索引是一种加快查询速度的数据结构,常用索引结构有hash、B-Tree和B+Tree。本节通过分析三者的数据结构来说明为啥Mysql选择用B+Tree数据结构。数据结构Hash hash是基于哈希表完成索引存储,哈希表特性是数据存放是散列的。优点:等值查询快,
Mysql存储结构
2017-09-11

kotlin源码结构层次详解

这篇文章主要为大家介绍了kotlin源码结构层次详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

教育层次结构的具体分析

  这种结构的最大特点就是将一个大型复杂的系统分解成若干单向依赖的层次,即每一层都提供一组功能且这些功能只依赖该层以内的的各层。其最内部的一层为系统核,具有初级中断处理、外部设备驱动、在进程之间切换处理机以及实施进程控制和通信的功能,其目的为提供一种进程可以存在和活动的环境。系统核以外依次为储存管理层、I/O处理层,文
教育层次结构的具体分析
2024-04-18

Java Swing的层次结构怎么理解

这篇文章主要介绍“Java Swing的层次结构怎么理解”,在日常操作中,相信很多人在Java Swing的层次结构怎么理解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java Swing的层次结构怎么理解
2023-06-21

redis各种数据类型底层数据存储结构

redis 的数据类型使用不同的底层存储结构:字符串:简单动态字符串(sds)哈希:哈希表,使用链表或跳跃表处理哈希碰撞列表:双向链表集合:哈希表或整数集合,使用布隆过滤器有序集合:跳跃表或字典地理空间索引:跳跃表或 r 树Redis 数据
redis各种数据类型底层数据存储结构
2024-04-19

C#构造函数的结构层次关系是怎样的

这篇文章主要介绍“C#构造函数的结构层次关系是怎样的”,在日常操作中,相信很多人在C#构造函数的结构层次关系是怎样的问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#构造函数的结构层次关系是怎样的”的疑惑有所
2023-06-17

oracle逻辑存储结构

oracle数据库管理系统有三个重要的概念:实例、数据库、数据库服务器。oracle数据库的存储结构可以分为逻辑存储结构和物理存储结构。逻辑存储结构用于描绘Oracle内部组织和管理数据的方式,而物理存储结构用于展示Oracle在操作系统中的物理文件组成情况。
2019-06-26

PostgreSQL数据库体系结构-存储结构

PostgreSQL数据库体系结构-存储结构数据库聚簇逻辑结构(Logical Structure of Database Cluster)database cluster--数据库聚簇,是一组数据库的集合,而不是多个数据库服务器database--数据库,是
PostgreSQL数据库体系结构-存储结构
2021-08-02

层次化数据结构下的Level函数选择

在层次化数据结构(如树形结构或图形结构)中,Level 函数通常用于选择特定层级的节点广度优先遍历(BFS):从根节点开始,按照层级顺序访问每个节点。在这种方法中,可以使用队列来实现。将根节点入队,然后在每一层遍历时,将当前层的所有节点出队
层次化数据结构下的Level函数选择
2024-09-03

C++ 中继承如何用于构建类层次结构?

c++++ 继承用于构建类层次结构,新类(派生类)从基类继承功能并扩展其功能。派生类使用访问说明符声明继承关系,控制对基类成员的访问权限。public 授予派生类和外部代码访问权限,protected 授予派生类及其派生类的访问权限,pri
C++ 中继承如何用于构建类层次结构?
2024-05-24

怎样理解Linux的存储结构

怎样理解Linux的存储结构,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。什么是目录? Windows下管C:\,D:\,E:\,F:\ 都是根目录而在linu
2023-06-16

MySQL 数据库的存储结构 - G

MySQL 数据库的存储结构 数据库存储结构从小到大、行>页 >区>段>表空间 (在Oracle中将页称为"块")页是数据库管理存储空间的基本单位,即,数据库I/O的最小单位是页InnoDB默认页大小为16K,可以通过show variavles like "
MySQL 数据库的存储结构 - G
2018-03-13

PHP数据结构之图存储结构的示例分析

这篇文章主要介绍PHP数据结构之图存储结构的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!图的存储结构图的概念介绍得差不多了,大家可以消化消化再继续学习后面的内容。如果没有什么问题的话,我们就继续学习接下来的
2023-06-20

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录