程序执行的基本过程
简单总结:一个程序执行的时候,CPU 会根据程序计数器里的内存地址,从内存里面把需要执行的指令读取到指令寄存器里面执行,然后程序计数器根据指令长度自增,开始顺序读取下一条指令。
CPU 从程序计数器读取指令、到执行、再到下一条指令,这个过程会不断循环,直到程序执行结束,这个不断循环的过程被称为 CPU 的指令周期。
冯诺依曼模型定义了计算机基本结构:运算器、控制器、存储器、输入输出设备。
内存
我们的程序和数据都是存储在内存,存储的区域是线性的。
在计算机数据存储中,存储数据的基本单位是字节(byte),1 字节等于 8 位(8 bit)。每一个字节都对应一个内存地址。
中央处理器(CPU)
中央处理器也就是我们常说的 CPU,32 位和 64 位 CPU 最主要区别在于一次能计算多少字节数据。这里的32位和64位,通常表示CPU的位宽。
CPU内部还有一些组件,常见的有寄存器,控制单元和逻辑运算单元
控制单元:负责控制CPU的工作。
逻辑运算单元:负责运算。
寄存器:存储计算时的数据,由于内存离CPU太远了,而寄存器就在CPU内部,计算速度更快。寄存器有以下几种:
总线
负责各种设备之间的通信。比如CPU读取内存数据时,要通过三个总线:
线路位宽与CPU位宽
线路位宽:数据在线路中传输,其实是通过操作电压,低电压表示0,高电压表示1。这样一位一位进行传输的方式称为串行,想要一次性多传输数据,可以增加线路的位宽。比如CPU 想要操作内存地址就需要地址总线,可以通过增加线路位宽的方式,增加CPU能操作的最大内存地址数量。(注意,不是说同时操作的最大内存地址数量)
2 ^ 32 = 4G
。(32位对应有232个地址,对应的内存数是232 * 8bit=4Gbyte即4GB)CPU位宽:CPU 的位宽最好不要小于线路位宽,否则工作起来会非常复杂且麻烦。如果计算的数额不超过 32 位数字的情况下,32 位和 64 位 CPU 之间没什么区别的,只有当计算超过 32 位数字的情况下,64 位的优势才能体现出来。
2^64
。a = 1 + 2的执行具体过程
程序—>汇编语言—>计算机指令
CPU 是不认识 a = 1 + 2
这个字符串,这些字符串只是方便我们程序员认识,要想这段程序能跑起来,还需要把整个程序翻译成汇编语言的程序,这个过程称为编译成汇编代码。针对汇编代码,我们还需要用汇编器翻译成机器码,这些机器码由 0 和 1 组成的机器语言,这一条条机器码,就是一条条的计算机指令,这个才是 CPU 能够真正认识的东西。
程序编译过程中,编译器分析代码,发现1和2是数据,所以放在内存中的「数据段」,编译器会把a = 1 + 2翻译成4条指令,存放到正文段中。
编译完成后,具体执行程序的时候,程序计数器会被设置为 0x100 地址,然后依次执行这 4 条指令。
上面的例子中,由于是在 32 位 CPU 执行的,因此一条指令是占 32 位大小,所以你会发现每条指令间隔 4 个字节。而数据的大小是根据你在程序中指定的变量类型,比如 int
类型的数据则占 4 个字节,char
类型的数据则占 1 个字节。
你知道软件的 32 位和 64 位之间的区别吗?再来 32 位的操作系统可以运行在 64 位的电脑上吗?64 位的操作系统可以运行在 32 位的电脑上吗?如果不行,原因是什么?
64 位和 32 位软件,实际上代表指令是 64 位还是 32 位的:
总之,硬件的 64 位和 32 位指的是 CPU 的位宽,软件的 64 位和 32 位指的是指令的位宽。
CPU时钟频率:1GHz表示该CPU的时钟频率是1G,表示1秒会发出1G次数的脉冲信号,每一次脉冲信号的高低电平就是一个时钟周期。时钟周期时间越短,CPU运算的越快。
机械硬盘、固态硬盘、内存这三个存储器,到底和 CPU L1 Cache
相比速度差多少倍呢?
CPU L1 Cache 随机访问延时是 1 纳秒,内存则是 100 纳秒,所以 CPU L1 Cache 比内存快 100 倍左右。
SSD 随机访问延时是 150 微秒,所以 CPU L1 Cache 比 SSD 快 150000 倍左右。
最慢的机械硬盘随机访问延时已经高达 10 毫秒,CPU L1 Cache 比机械硬盘快 10000000 倍左右;
寄存器
寄存器用来存储计算的数据,是最靠近 CPU 的控制单元和逻辑计算单元的存储器。
寄存器的价格很贵,数量通常在几十到几百之间,每个寄存器可以用来存储一定的字节(byte)的数据。比如:
寄存器的访问速度非常快,一般要求在半个 CPU 时钟周期内完成读写,CPU 时钟周期跟 CPU 主频息息相关,比如 2 GHz 主频的 CPU,那么它的时钟周期就是 1/2G,也就是 0.5ns(纳秒)。
CPU Cache
CPU Cache 用的是一种叫 SRAM(Static Random-Access Memory,静态随机存储器) 的芯片。静态,说明有电时数据一直存在,但掉电数据丢失。
在 SRAM 里面,一个 bit 的数据,通常需要 6 个晶体管,所以 SRAM 的存储密度不高,同样的物理空间下,能存储的数据是有限的,不过也因为 SRAM 的电路简单,所以访问速度非常快。
CPU 的高速缓存,通常可以分为 L1、L2、L3 三层高速缓存,也称为一级缓存、二级缓存、三级缓存。
L1 高速缓存是每个CPU Core独有的,访问速度快,只需要 2~4 个时钟周期。大小在几十 KB 到几百 KB 不等。
L1 高速缓存的指令和数据是分开存放的,所以 L1 高速缓存通常分成指令缓存和数据缓存。
L2 高速缓存同样每个 CPU 核心都有,但是 L2 比L1 距离 CPU 核心更远,访问速度则更慢,速度在 10~20 个时钟周期。但大小比 L1 更大,通常大小在几百 KB 到几 MB不等,
L3 高速缓存通常是多个 CPU 核心共用的,位置比 L2 高速缓存距离 CPU 核心 更远,访问速度相对也比较慢一些,访问速度在 20~60 个时钟周期。大小也会更大些,通常大小在几 MB 到几十 MB 不等。
内存
内存用的芯片和 CPU Cache 有所不同,它使用的是一种叫作 DRAM (Dynamic Random Access Memory,动态随机存取存储器) 的芯片。动态,因为数据会被存储在电容里,电容会不断漏电,所以需要定时刷新电容,才能保证数据不会被丢失。
相比 SRAM,DRAM 的密度更高,功耗更低,有更大的容量,而且造价比 SRAM 芯片便宜很多。存储一个 bit 数据,只需要一个晶体管和一个电容就能存储。
DRAM 的数据访问电路和刷新电路都比 SRAM 更复杂,所以访问的速度会更慢,内存速度大概在 200~300 个 时钟周期之间。
SSD/HDD硬盘
固态硬盘(Solid-state disk,SSD) 结构和内存类似。相比寄存器/Cache/内存的优点是断电后数据还存在;缺点是读写速度很慢。
机械硬盘(Hard Disk Drive, HDD),通过物理读写的方式来访问数据的,因此它访问速度是非常慢的,它的速度比内存慢 10W 倍左右。由于 SSD 的价格快接近机械硬盘了,因此机械硬盘已经逐渐被 SSD 替代了。
存储器的层次关系
CPU 并不会直接和每一种存储器设备直接打交道,而是每一种存储器设备只和它相邻的存储器设备打交道。比如,CPU Cache 的数据是从内存加载过来的,写回数据的时候也只写回到内存,再从内存写回到硬盘中。
不同的存储器之间性能差距很大,构造存储器分级很有意义,分级的目的是要构造缓存体系。这样的访问机制,跟我们使用「内存作为硬盘的缓存」的逻辑是一样的。
CPU Cache有多快?
根据摩尔定律,CPU 的访问速度每 18 个月就会翻倍,相当于每年增长 60% 左右,内存的速度当然也会不断增长,但是增长的速度远小于 CPU,平均每年只增长 7% 左右。于是,CPU 与内存的访问性能的差距不断拉大。到现在,一次内存访问所需时间是 200~300 多个时钟周期,这意味着 CPU 和内存的访问速度已经相差 200~300 多倍了。
为了弥补 CPU 与内存两者之间的性能差异,就在 CPU 内部引入了 CPU Cache,也称高速缓存。
CPU Cache 数据结构?
CPU Cache 是由很多个 Cache Line 组成的,Cache Line (缓存块)是 CPU 从内存读取数据的基本单位。
Cache Line 结构
内存地址与Cache Line的直接映射
CPU 访问内存数据时,是一小块一小块数据读取的,具体这一小块数据的大小,取决于 coherency_line_size 的值,一般 64 字节。在内存中,这一块的数据我们称为内存块(Block),读取的时候我们要拿到数据所在内存块的地址。
一个内存的访问地址,包括组标记、CPU Cache Line 索引、偏移量这三种信息,于是 CPU 就能通过这些信息,在 CPU Cache 中找到缓存的数据。
CPU Cache 读写过程?
根据内存地址中索引信息,计算在 CPU Cache 中的索引,也就是找出对应的 CPU Cache Line 的地址;
找到对应 CPU Cache Line 后,判断 CPU Cache Line 中的有效位,确认 CPU Cache Line 中数据是否是有效的,如果是无效的,CPU 就会直接访问内存,并重新加载数据,如果数据有效,则往下执行;
对比内存地址中组标记和 CPU Cache Line 中的组标记,确认 CPU Cache Line 中的数据是我们要访问的内存数据,如果不是的话,CPU 就会直接访问内存,并重新加载数据,如果是的话,则往下执行;
根据内存地址中偏移量信息,从 CPU Cache Line 的数据块中,读取对应的字。
写出让CPU跑得更快的程序
CPU操作L1 Cache的速度是很快的,提升CPU运行速度,可以提升访问L1 Cache的速度。
那么L1 Cache 通常分为「数据缓存」和「指令缓存」,因此要分别提高「数据缓存」和「指令缓存」的缓存命中率。
提升数据缓存的命中率
CPU会一次从内存中加载多少元素到 CPU Cache ,可以在Linux 里通过 coherency_line_size 配置查看 它的大小,通常是 64 个字节。
如果遇到遍历数组之类的情况时,按照内存布局顺序访问,将可以有效的利用 CPU Cache 带来的好处,这样我们代码的性能就会得到很大的提升。
提升指令缓存的命中率
使用显式分支预测工具,如果分支预测可以预测到接下来要执行 if 里的指令,还是 else 指令的话,就可以「提前」把这些指令放在指令缓存中,这样 CPU 可以直接从 Cache 读取到指令,于是执行速度就会很快。
还可以提升多核CPU的缓存命中率
L2 Cache和L1 Cache 是每个核心独有的,如果一个线程在不同核心来回切换,各个核心的缓存命中率就会受到影响,可以把线程绑定到某一个CPU核心上。
在 Linux 上提供了 sched_setaffinity 方法,来实现将线程绑定到某个 CPU 核心这一功能。
整理自:小林coding
聚圣源给小孩起名字大全乳名2018出生起名打分勃朗宁起名大全 易经端午节文案架空历史小说排行榜猴怎么样起名带草字头的字起名银翼杀手2049下载侠盗飞车圣安地列斯怎么泡妞公司起名常用字a频道神将世界辅助袁起名字大全男孩好听的黄姓男孩起名中华免费起名网站大全给宝宝起名的网站哪个好吗冤罪ovawww.porhub.com水饺店 起名18空间周易起名软件注册码起名网页免费麻布依10100556是什么电话?韩姓起名韩姓起名公司测名起名酒类个体工商户起名多人合伙的公司起个名独臂神尼淀粉肠小王子日销售额涨超10倍罗斯否认插足凯特王妃婚姻让美丽中国“从细节出发”清明节放假3天调休1天男孩疑遭霸凌 家长讨说法被踢出群国产伟哥去年销售近13亿网友建议重庆地铁不准乘客携带菜筐雅江山火三名扑火人员牺牲系谣言代拍被何赛飞拿着魔杖追着打月嫂回应掌掴婴儿是在赶虫子山西高速一大巴发生事故 已致13死高中生被打伤下体休学 邯郸通报李梦为奥运任务婉拒WNBA邀请19岁小伙救下5人后溺亡 多方发声王树国3次鞠躬告别西交大师生单亲妈妈陷入热恋 14岁儿子报警315晚会后胖东来又人满为患了倪萍分享减重40斤方法王楚钦登顶三项第一今日春分两大学生合买彩票中奖一人不认账张家界的山上“长”满了韩国人?周杰伦一审败诉网易房客欠租失踪 房东直发愁男子持台球杆殴打2名女店员被抓男子被猫抓伤后确诊“猫抓病”“重生之我在北大当嫡校长”槽头肉企业被曝光前生意红火男孩8年未见母亲被告知被遗忘恒大被罚41.75亿到底怎么缴网友洛杉矶偶遇贾玲杨倩无缘巴黎奥运张立群任西安交通大学校长黑马情侣提车了西双版纳热带植物园回应蜉蝣大爆发妈妈回应孩子在校撞护栏坠楼考生莫言也上北大硕士复试名单了韩国首次吊销离岗医生执照奥巴马现身唐宁街 黑色着装引猜测沈阳一轿车冲入人行道致3死2伤阿根廷将发行1万与2万面值的纸币外国人感慨凌晨的中国很安全男子被流浪猫绊倒 投喂者赔24万手机成瘾是影响睡眠质量重要因素春分“立蛋”成功率更高?胖东来员工每周单休无小长假“开封王婆”爆火:促成四五十对专家建议不必谈骨泥色变浙江一高校内汽车冲撞行人 多人受伤许家印被限制高消费