CPU扫盲-CPU如何执行指令以及流水线技术

  在CPU扫盲-CPU与指令集中阐述了CPU与指令集之间的关系,并在CPU扫盲-自研指令集中以创造者的身份深入讲解了指令集,这篇文章则是针对CPU的专场,以x86架构下的CPU为例具体分析一下CPU如何执行指令。

  计算机基本硬件由控制器、储存器、运算器、输入设备、输出设备五大部件组成,其中运算器、控制器、部分储存器被集成在一起统称为中央处理单元(Central Processing Unit,CPU)。CPU 大体上可以划分为三个部分,它们是控制单元运算单元存储单元,他们互相配合执行一条指令。

  控制单元由指令寄存器IR( Instruction Register )、指令译码器 ID (Instruction oder )、操作控制器 OC (Operation Controller) 组成。程序被加载到内存后,指令这时都在内存中了,指令指针寄存器IP(cs:ip)指向内存中下一条待执行指令的地址,操作控制器 OC根据cs:ip的指向,将位于内存中的指令装载到指令寄存器IR中。然后指令译码器ID将位于指令寄存器IR中的指令按照指令集格式(对指令集不熟悉的可以先看下CPU扫盲-自研指令集)来解码,分析操作码和操作数,如果指令中的操作数为内存寻址,需要将内存中的数据取出暂存到储存单元储存单元指的是CPU内部的L1/L2缓存(SRAM 缓存)以及寄存器,很多同学在感观上觉得寄存器是 CPU 直接使用的存储单元,所以寄存器比SRAM 更快 其实它们在速度上是同一级别的东西,因为寄存器和 SRAM 都是用相同的存储电路实现的,用的都是触发器,它工作速度极快,属于纳秒级别。CPU的寄存器分为可见和不可见两大类。可见就是程序可见,可以通过指令控制的寄存器如:PC寄存器、通用寄存器、段基址寄存器等;不可见的就是硬件直接使用,程序不可见不可操控的寄存器如:指令寄存器IR,L1/L2缓存也可看作特殊的不可见寄存器。


  现在操作码和操作数都准备好了,就差执行指令了,如果这个指令是加减乘除等算数运算,操作控制器OC会给运算单元发送信号执行指令;如果指令是赋值、函数调用等操作则由操作控制器 OC直接执行。就这样一条指令执行完毕,整个过程包括取码、译码、执行,接着控制单元又要取下一条指令了,流程回到了本段开头, CPU的工作就是这样一天天的重复、循环。

  上文介绍了CPU如何执行一条指令的。那接下来看下CPU是如何执行多条指令的,有同学会疑问上面不是说了嘛,执行完当前指令再去获取下一条指令不断重复循环,多循环几次不就是多条指令了嘛。注意上文的重点是CPU执行一条指令时控制单元运算单元存储单元之间是如何配合的,将一条指令的执行划分为取码、译码、执行三个步骤,这更像是理论,为了方便大家理解,但真正CPU厂商在设计CPU电路时会复杂的多,能将一个指令的执行划分为几十个步骤。如:x86系列CPU由于其指令不定长缘故,取码的过程就拆分成了多个小步骤,假设CPU为32位,指令指针寄存器IP(cs:ip)为 0x00000000,当前指令长24bit。

  1. 内存获取指令:由于CPU数据总线宽32bit,所以一次寻址获取32bit数据,将数据暂存SRAM 缓存
  2. 指令预处理:由于x86指令非定长,所以需要预处理,对指令进行部分译码分析出操作码判断出指令长度为24bit
  3. 存入指令寄存器IR:在32bit数据中取出有效部分存入指令寄存器IR
  4. 更新指令指针寄存器IP:当前指令长度为24bit=3字节,所以下一条指令地址应为0x00000003,更新指令指针寄存器IP为 0x00000003

  借助这个例子也想强调一下cs:ip的值在取码完成后就会被更新为下一条指令的地址,并非必须等当前指令执行完毕才更新。这个地方如果误解了后续CPU流水线技术的学习就不容易理解。

  CPU在电路设计上实现了多个独立电路,支持每个步骤独立执行,CPU 可以一边执行指令,一边取指令,一边译码。虽然CPU在同一时刻只能执行一条指令,由于cs:ip的值在取码完成后就会被更新为下一条指令的地址,所以在执行这条指令的同时可以去翻译下一条指令,同时去获取下下条指令。这样的流水线模式大大提升CPU的执行效率,下面我们用取码、译码、执行三级流水线为例来讲一下CPU的流水线技术,见下图:

  以上在第2周期后,虽然在一个时钟周期内 CPU 同时干了三件事,但一定要清楚,这三件事不属于一个指令,是三个指令重叠在一起了。同时完成的是当前指令的第三步、下一条指的第二步、第三条指令的第一步。 CPU 中每条指令必须经过取指、译码、执行三步才算完成。三级流水线模型就是要保证取码、译码、执行三个独立的电路始终在运行状态不要停下来。就拿周期3来说,在这一时钟周期里, CPU 同时完成了“执行”、“译码”、“取指” 三件事。其中“执行电路”处理第一条指令的执行步骤,“译码电路”处理第二条指令的译码步骤,”取指电路“处理第三条指令的取码步骤。

  如果CPU不使用流水线技术的话执行一个指令始终需要三个周期,执行10000条指令需要 10000(指令数) x 3 (单个步骤耗时) + 0(3单条指令总耗时-3单步骤耗时)=30000 个周期;在使用三级流水线技术时(如上图),将每条指令的执行划分为三个步骤,因为每条指令执行的总耗时相同都为三个周期,所以每个步骤耗时一个周期,相当于从第三个周期开始每执行一条指令只需要一个周期,执行10000条指令需要 10000(指令数) x 1 (单个步骤耗时) + 2(3单条指令总耗时-1单步骤耗时)=10002个周期;试想如果使用10级流水线技术(如下图),将每条指令的执行划分为10个步骤,每条指令执行的总耗为3周期不变的前提下,10级流水线每个步骤耗时0.3周期,相当于从第3.0个周期开始每执行一条指令只需要0.3个周期,此时执行10000条指令只需要 10000(指令数) x 0.3 (单个步骤耗时) + 2.7(3单条指令总耗时-0.3单步骤耗时)=3002.7个周期,这大大提升了CPU的性能,此时 CPU10级流水线的性能相较与CPU不使用流水线技术时的性能已经提升了一个数量级。

在这里插入图片描述

  按照上述论证,CPU的支持的流水线条数和CPU的性能是成正比的,CPU的流水线条数真的越多越好嘛?很可惜CPU的流水线条数并不是越多越好,有两个主要原因:

  1. CPU多流水线的原理是将CPU划分为多个独立电路,每个电路负责指令执行的一个步骤。流水线条数越多CPU的电路就越复杂,CPU的体积就会越大,CPU的能耗就会越高,这种高能耗CPU靠电池供电的移动设备就无法接受,因为相比性能过剩的CPU人们更看重它的续航表现,所以CPU设计人员需要在性能和功耗之间做一个很好的平衡,不能一味的追求性能。
  2. 上述CPU流水线条数和CPU性能成正比的结论是在程序指令依次执行的情况下,但当程序指令出现跳转或分支结构时就要另当别论了。比如当上图的第一条指令是jmp (无条件的转移到指令指定的地址去执行从该地址开始的命令)指令时,jmp指令会直接修改指令指针寄存器IP中的指令地址,所以当第3.0个周期jmp指令执行时,指令指针寄存器IP中的指令地址会被更新,下一条指令应该是更新后新地址的第一条指令,之前流水线中的指令二到指令十都是无效指令了,这个时候就需要清空流水线中的指令,就意味着清空所有的独立电路以及相关寄存器,这个过程显然流水线越多 耗时越多 代价越大。当然CPU也会有分支预测等手段来尽量避免这种清空流水线的情况发生(不能完全避免),但同样需要复出很大代价比如:电路更加复杂,CPU成本更高。所以CPU的流水线并不是越多越好,CPU的设计师要兼顾方方面面。
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

躺平程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值