今日文章:
小林coding:CPU 是如何执行程序的?
目录
- 内存
- 中央处理器
- 指令及其周期
- 指令类型
- MIPS指令类型
- 指令周期
- 指令的执行速度
冯诺依曼计算机遵循了图灵机的设计,使用了电子元件构造,约定了用二进制进行计算和存储
图灵机基本由纸带和和读写头组成,读写头上有存储单元,控制单元和运算单元
冯诺依曼模型定义了计算机基本结构为5部分:运算器、控制器、存储器、输入设备、输出设备
关系大致如图,运算器和控制器在中央处理器中,存储器为内存,输入输出设备则是计算器外接的设备
内存
内存存储数据的基本单位是字节(byte),1字节等于8位(8bit)
程序和数据都存储在内存中,内存的存储区域是线性的,地址从0开始编号,自增排列,所以内存读写任何一个数据的速度基本一致
中央处理器
即CPU,32位和64位CPU最主要的区别在于一次能处理多少字节数据
32位寄存器一次能计算的最大整数是4294967295,即 2 32 2^{32} 232
32CPU配32位地址总线理论最大寻址空间为4GB,若需访问更大内存,需通过内存分段映射(如 PAE)等技术实现逻辑扩展。所以理论上32位CPU最大只能操作4GB内存,而64位CPU寻址范围则很大,理论上最大的寻址空间为 2 64 2^{64} 264,但受硬件和系统限制,实际支持的内存通常为 GB 至 TB 级。
指令及其周期
指令类型
指令的类型指令从功能角度划分,可以分为 5 大类:
- 数据传输类型的指令,比如 store/load 是寄存器与内存间数据传输的指令,mov 是将一个内存地址的数据移动到另一个内存地址的指令;
- 运算类型的指令,比如加减乘除、位运算、比较大小等等,它们最多只能处理两个寄存器中的数据;
- 跳转类型的指令,通过修改程序计数器的值来达到跳转执行指令的过程,比如编程中常见的 if-else、switch-case、函数调用等。
- 信号类型的指令,比如发生中断的指令 trap;
- 闲置类型的指令,比如指令 nop,执行后 CPU 会空转一个周期;
MIPS指令类型
- R 指令,用在算术和逻辑操作,里面有读取和写入数据的寄存器地址。如果是逻辑位移操作,后面还有位移操作的「位移量」,而最后的「功能码」则是再前面的操作码不够的时候,扩展操作码来表示对应的具体指令的;
- I 指令,用在数据传输、条件分支等。这个类型的指令,就没有了位移量和功能码,也没有了第三个寄存器,而是把这三部分直接合并成了一个地址值或一个常数;
- J 指令,用在跳转,高 6 位之外的 26 位都是一个跳转后的地址;
指令周期
CPU读取程序计数器对应内存地址的指令,称为Fetch
CPU对指令进行解码,称为Decode
CPU执行指令,这个部分称为Execution
CPU将计算结果存回寄存器或者将寄存器的值存入内存,这个部分称为Store
CPU读取[程序计数器]的值,这个值是指令的内存地址,然后CPU的[控制单元]通过[地址总线]通知内存,内存将对应数据通过[数据总线]传给CPU,CPU的[控制单元]将收到的数据暂存到[指令寄存器],[程序计数器]自增指向下一条指令
[控制单元]解析[指令寄存器]中的指令,确定指令的类型和参数
将计算类型的指令,交给算数逻辑单元处理,其他指令由控制单元处理
最后有结果将结果写回到内存或其他寄存器
指令的执行速度
CPU的时钟频率指每秒产生的脉冲信号次数,而每次脉冲信号高低电平的转换就是一个周期,称为时钟周期
指令的执行主要看指令所需的CPU时钟周期数以及CPU时钟周期
主频越高,CPU时钟周期越短,CPU工作速度就越快
想要程序跑的快,可以从以下三点进行优化:
- 指令数,表示执行程序所需要多少条指令,以及哪些指令。这个层面是基本靠编译器来优化,毕竟同样的代码,在不同的编译器,编译出来的计算机指令会有各种不同的表示方式。
- 每条指令的平均时钟周期数 CPI,表示一条指令需要多少个时钟周期数,现代大多数 CPU 通过流水线技术(Pipeline),让一条指令需要的 CPU 时钟周期数尽可能的少;
- 时钟周期时间,表示计算机主频,取决于计算机硬件。有的 CPU 支持超频技术,打开了超频意味着把 CPU 内部的时钟给调快了,于是 CPU 工作速度就变快了,但是也是有代价的,CPU 跑的越快,散热的压力就会越大,CPU 会很容易奔溃。