计算机组成
一、计算机组成原理
5 个部分组成:运算器、控制器、存储器、输入设备、输出设备
中央处理器
32 位和 64 位 CPU 最主要区别在于一次能计算多少字节数据
:
- 32 位 CPU 一次可以计算 4 个字节;
- 64 位 CPU 一次可以计算 8 个字节;
不代表 64 位 CPU 性能比 32 位 CPU 高很多,很少应用需要算超过 32 位的数字,所以如果计算的数额不超过 32 位数字的情况下,32 位和 64 位 CPU 之间没什么区别的,只有当计算超过 32 位数字的情况下,64 位的优势才能体现出来。
CPU 内部有寄存器、控制单元和逻辑运算单元等,控制单元负责控制 CPU 工作,逻辑运算单元负责计算,而寄存器可以分为多种类。
- 通用寄存器,用来存放需要进行运算的数据,比如需要进行加和运算的两个数据。
- 程序计数器,用来存储 CPU 要执行下一条指令「所在的内存地址」,注意不是存储了下一条要执行的指令,此时指令还在内存中,程序计数器只是存储了下一条指令「的地址」。
- 指令寄存器,用来存放当前正在执行的指令,也就是指令本身,指令被执行完成之前,指令都存储在这里。
总线
总线是用于 CPU 和内存以及其他设备之间的通信,总线可分为 3 种:
- 地址总线,用于指定 CPU 将要操作的内存地址;
- 数据总线,用于读写内存的数据;
- 控制总线,用于发送和接收信号,比如中断、设备复位等信号,CPU 收到信号后自然进行响应,这时也需要控制总线;
## CPU进行一次访问内存的具体步骤:
首先要通过「地址总线」来指定内存的地址;
然后通过「控制总线」控制是读或写命令;
最后通过「数据总线」来传输数据;
CPU 位宽的意义?
CPU 的位宽最好不要小于线路位宽, 32 位 CPU 一次最多只能操作 32 位宽的地址总线和数据总线,想要 CPU 操作 4G 大的内存,那么就需要 32 条地址总线,因为 2 ^ 32 = 4G
数字表示
1、原码:一个数的正常二进制表示,最高位表示符号,数值0的源码有两种形式: +0 (0 0000000) 和-0 (1 0000000)
2、反码:正数的反码即原码:负数的反码是在原码的基础上,除符号位外,其他各位按位取反。数值0的反码也有两种形式: +0 (0 0000000),-0 (11111111)
3、补码:正数的补码即原码;负数的补码是在原码的基础上,除符号位外,其他各位按位取反,而后末位+1,若有进位则产生进位。因此数值0的补码只有一种形式+0=-0=0.0000000
4、移码: 用作浮点运算的阶码,无论正数负数,都是将该原码的补码的首位(符号位) 取反得到移码。
存储器
- 寄存器->Cache->主存->辅存->外存
- Cache-主存:解决了主存与CPU速度不匹配的问题。
- 主存-辅存:实现虚拟存储系统,解决了主存容量不够的问题。
Ⅰ、按照存取方式:分为随机存取存储器(RAM),如内存;顺序存取存储器(SAM),如磁带;直接存取存储器(Direct-Access),如磁盘;相联存储器(可按内容访问的存储器,CAM),如快表。
Ⅱ、按信息是否可改:分为读/写存储器和只读存储器(ROM)
Ⅲ、断电后是否消失:分为易失性存储器,如内存、Cache;非易失性存储器,如磁盘、光盘
SRAM和DRAM
- 工作原理不同:SRAM 在工作时不需要刷新,而 DRAM 在工作时需要定期刷新,否则数据就会丢失。
- 速度不同:SRAM 的速度要快于 DRAM,因为 SRAM 在工作时不需要刷新,而 DRAM 需要定期刷新,这会使 DRAM 的速度变慢。
- 容量不同:SRAM 的容量通常比 DRAM 小,因为 SRAM 每个存储单元都包含较多的电路元件,而 DRAM 则每个存储单元只包含一个电容。
- 价格不同:由于 SRAM 的生产成本较高,所以 SRAM 的价格通常比 DRAM 贵。
通常情况下,SRAM 用作缓存存储器,而 DRAM 则用作主存储器。
ROM只读存储器
- ①MROM——掩模式只读存储器:任何人都不可重写
- ②PROM——可编程只读存储器:写一次后就不可更改
- ③EPROM——可擦除可编程只读存储器:可进行多次重写,写入时间很长
- ④Flash Memory——闪速存储器:可进行多次快速擦除重写,但写的速度比读的速度慢
Cache高速缓存
Cache存储器也被称为高速缓冲存储器,位于CPU和主存储器之间。之所以在CPU和主存之间要加cache是因为现代的CPU频率大大提高,内存的发展已经跟不上CPU访存的速度。在现在的系统中,处理器需要上百个时钟周期才能从主存中取到数据。如果没有cache,处理器在等待数据的大部分时间内将会停滞不动。
- 时间局部性:如果一个数据现在被访问了,那么以后很有可能也会被访问
- 空间局部性:如果一个数据现在被访问了,那么它周围的数据在以后可能也会被访问
为什么要用多级cache?
原因在于性能/功耗/面积(PPA)权衡考虑。
L1 cache一般工作在CPU的时钟频率,要求的就是够快,可以在2-4时钟周期内取到数据。L2 cache相对来说是为提供更大的容量而优化的。虽然L1和L2往往都是SRAM,但构成存储单元的晶体管并不一样。L1是为了更快的速度访问而优化过的,它用了更多/更复杂/更大的晶体管,从而更加昂贵和更加耗电;L2相对来说是为提供更大的容量优化的,用了更少/更简单的晶体管,从而相对便宜和省电。在有一些CPU设计中,会用DRAM实现大容量的L3 cache。
cache一致性策略
## Ⅰ、写命中——写入的时候,在Cache中
①回写法:当CPU对Cache写命中时,只修改Cache的内容,而不立即写入主存,只有当次块被换出时才写回主存。减少了访存次数,但存在数据不一致的隐患。被换出时,看”脏位“是否知道是否被修改。
②全写法:当CPU对Cache写命中时,必须把数据同时写入Cache和主存,一般使用写缓冲。访存次数增加,速度变慢,但是能保证数据的一致性。无脏位。
## Ⅱ、写不命中——写入的时候,不在Cache中
①写分配法——当CPU对Cache不命中时,把主存中的块调入Cache,在Cache中修改。通常搭配**回写法**使用,改完后要被换出,才在主存中修改。
②非写分配法——当CPU对Cache写不命中时,只写入主存,不调入Cache,搭配全写法使用。
虚拟存储
页式虚拟 + 快表
段式虚拟
虚拟地址:段号+段内地址
优点:段的分界与程序的自然分界相对应,因而具有逻辑独立性,使得它易于编译、管理、修改和保护。
缺点:段的长度可变,分配空间不便,容易留下碎片,不好利用,造成浪费。
段页式虚拟存储
把程序按逻辑结构分段,每段在分固定大小的页,主存空间也划分为大小相等的页,每个程序对应一个段表,每段对应一个页表。
虚拟地址:段号+段内地址+页内地址
二、程序执行的基本过程
- 第一步,CPU 读取「程序计数器」的值,这个值是指令的内存地址,然后 CPU 的「控制单元」操作「地址总线」指定需要访问的内存地址,接着通知内存设备准备数据,数据准备好后通过「数据总线」将指令数据传给 CPU,CPU 收到内存传来的数据后,将这个指令数据存入到「指令寄存器」。
- 第二步,「程序计数器」的值自增,表示指向下一条指令。这个自增的大小,由 CPU 的位宽决定,比如 32 位的 CPU,指令是 4 个字节,需要 4 个内存地址存放,因此「程序计数器」的值会自增 4;
- 第三步,CPU 分析「指令寄存器」中的指令,确定指令的类型和参数,如果是计算类型的指令,就把指令交给「逻辑运算单元」运算;如果是存储类型的指令,则交由「控制单元」执行;
CPU 从程序计数器读取指令、到执行、再到下一条指令,这个过程会不断循环,直到程序执行结束,这个不断循环的过程被称为 CPU 的指令周期。
三、程序编译过程
a = 1 + 2
在 32 位 CPU 的执行过程:
程序编译过程中,编译器通过分析代码,发现 1 和 2 是数据,于是程序运行时,内存会有个专门的区域来存放这些数据,这个区域就是「数据段」,存放指令区域的地方称为「正文段」:
编译器会把 a = 1 + 2
翻译成 4 条指令,存放到正文段中。如图,这 4 条指令被存放到了 0x100 ~ 0x10c 的区域中:
- 0x100 的内容是
load
指令将 0x200 地址中的数据 1 装入到寄存器R0
; - 0x104 的内容是
load
指令将 0x204 地址中的数据 2 装入到寄存器R1
; - 0x108 的内容是
add
指令将寄存器R0
和R1
的数据相加,并把结果存放到寄存器R2
; - 0x10c 的内容是
store
指令将寄存器R2
中的数据存回数据段中的 0x208 地址中,这个地址也就是变量a
内存中的地址;
四、指令
不同的 CPU 有不同的指令集,也就是对应着不同的汇编语言和不同的机器码,复杂指令集CISC,精简指令集RISC。
精简指令集的特点是一条指令背后的动作更少,编译器对CPU的控制力更强,复杂指令集下,CPU会对编译器隐藏机器指令的执行细节.
在复杂指令集下,一条机器指令可能涉及到从内存中取出数据、执行一些操作比如加和、然后再把执行结果写回到内存中,但在精简指令集下,指令只能操作寄存器中的数据,内存中的数据通过load和store来存取,
指令的类型
指令从功能角度划分,可以分为 5 大类:
- 数据传输类型的指令,比如
store/load
是寄存器与内存间数据传输的指令,mov
是将一个内存地址的数据移动到另一个内存地址的指令; - 运算类型的指令,比如加减乘除、位运算、比较大小等等,它们最多只能处理两个寄存器中的数据;
- 跳转类型的指令,通过修改程序计数器的值来达到跳转执行指令的过程,比如编程中常见的
if-else
、switch-case
、函数调用等。 - 信号类型的指令,比如发生中断的指令
trap
; - 闲置类型的指令,比如指令
nop
,执行后 CPU 会空转一个周期;
指令的执行速度
一个 1 GHz 的 CPU,指的是时钟频率是 1 G,代表着 1 秒会产生 1G 次数的脉冲信号,每一次脉冲信号高低电平的转换就是一个周期,称为时钟周期。
对于 CPU 来说,在一个时钟周期内,CPU 仅能完成一个最基本的动作,时钟频率越高,时钟周期就越短,工作速度也就越快。
一个时钟周期不一定能执行完一条指令。大多数指令通常需要若干个时钟周期。不同的指令需要的时钟周期是不同的,加法和乘法都对应着一条 CPU 指令,但是乘法需要的时钟周期就要比加法多。
优化执行速度
时钟周期时间就是前面提及的 CPU 主频,CPU时钟周期数 = 指令数 * 每条指令的平均时钟周期数
优化这三者即可:
- 指令数,表示执行程序所需要多少条指令,以及哪些指令。这个层面是基本靠编译器来优化,毕竟同样的代码,在不同的编译器,编译出来的计算机指令会有各种不同的表示方式。
- 每条指令的平均时钟周期数 CPI,表示一条指令需要多少个时钟周期数,现代大多数 CPU 通过流水线技术(Pipeline),让一条指令需要的 CPU 时钟周期数尽可能的少;
- 时钟周期时间,表示计算机主频,取决于计算机硬件。有的 CPU 支持超频技术,打开了超频意味着把 CPU 内部的时钟给调快了,于是 CPU 工作速度就变快了,但是也是有代价的,CPU 跑的越快,散热的压力就会越大,CPU 会很容易奔溃。
流水线技术
指令步骤的并行。常见的六级流水线将指令流的处理过程划分为取指(FI)、译码(DI)、计算操作数地址(CO)、取操作数(FO)、执行指令(EI)、写操作数(WO)等几个并行处理的过程段。这就是指令6级流水时序。在这个流水线中,处理器有六个操作部件,同时对这六条指令进行加工,加快了程序的执行速度。
五、参考
https://zhuanlan.zhihu.com/p/554546968