计算机组成原理6-流水线、多发射和超标量、SIMD、异常

 

1、完整功能的CPU有3个周期概念:指令周期、机器周期、时钟周期

2、一条CPU指令的执行步骤:取得指令-指令译码-执行指令,这个过程至少花费一个时钟周期。

    单指令周期处理器:一个周期内,只执行一条指令。这样就需要保证时钟周期等于执行时间最长的指令时间。这样时钟频率就不能太高,否则指令可能还没有执行完成就开始执行下一条指令,而之前的指令计算结果还没有存到寄存器中。


这样的CPU实际效率并不高


3、流水线

    CPU 的指令执行过程,其实也是由各个电路模块组成的。在取指令的时候,需要一个译码器把数据从内存里面取出来,写入到寄存器中;在指令译码的时候,需要另外一个译码器,把指令解析成对应的控制信号、内存地址和数据;到了指令执行的时候,需要的则是一个完成计算工作的 ALU。把时钟周期设置成整条指令执行的时间,而是拆分成完成这样的一个一个小步骤需要的时间。同时,每一个阶段的电路在完成对应的任务之后,也不需要等待整个指令执行完成,而是可以直接执行下一条指令的对应阶段。


 

不需要确保最复杂的那条指令在时钟周期里面执行完成,而只要保障一个最复杂的流水线级的操作,在一个时钟周期内完成就好了。


4、 超长流水线

    流水线并没有缩短单条指令的响应时间,但是可以增加运行很多条指令时候的吞吐率。

    流水线深度的增加,需要的电路数量变多了,也就是使用的晶体管也就变多了。过深的流水线,不仅不能提升计算机指令的吞吐率,更会加大计算的功耗和散热问题。而流水线带来的吞吐率提升,只是一个理想情况下的理论值。在实践的应用过程中,还需要解决指令之间的依赖问题。这个使得流水线,特别是超长的流水线的执行效率变得很低。要想解决好冒险的依赖关系问题,需要引入乱序执行、分支预测等技术。


5、关于多发射和超标量

    通过增加硬件的方式,将取指令和指令译码实现并行,一次性取出多条指令,然后分发给多个并行的指令译码器,进行译码,然后对应交给不同的功能单元去处理。这样,在一个时钟周期里,能够完成的指令就不只一条了。这种 CPU 设计,叫作多发射(Mulitple Issue)和超标量(Superscalar)。

    多发射是指将多条指令同时发射到不同的译码器或者后续处理流水线中。

    超标量的CPU里面有很多并行的流水线,而不是单一一条。



6、单指令多数据流

    SIMD 在获取数据和执行指令的时候,都做到了并行。一方面,在从内存里面读取数据的时候,SIMD 是一次性读取多个数据。对于那些在计算层面存在大量“数据并行”(Data Parallelism)的计算中,使用 SIMD 是一个很划算的办法。在这个大量的“数据并行”,其实通常就是实践当中的向量运算或者矩阵运算。在实际的程序开发过程中,过去通常是在进行图片、视频、音频的处理。最近几年则通常是在进行各种机器学习算法的计算。


7、计算机是如何处理异常的

    关于异常,最有意思的一点就是,它其实是一个硬件和软件组合到一起的处理过程。异常的前半生,也就是异常的发生和捕捉,是在硬件层面完成的。但是异常的后半生,也就是说,异常的处理,其实是由软件来完成的。

    计算机会为每一种可能会发生的异常,分配一个异常代码(Exception Number)。有些教科书会把异常代码叫作中断向量(Interrupt Vector)。异常发生的时候,通常是 CPU 检测到了一个特殊的信号。比如,按下键盘上的按键,输入设备就会给 CPU 发一个信号。或者,正在执行的指令发生了加法溢出,同样,可以有一个进位溢出的信号。这些信号呢,在组成原理里面,一般叫作发生了一个事件(Event)。CPU 在检测到事件的时候,其实也就拿到了对应的异常代码。

 

    这些异常代码里,I/O 发出的信号的异常代码,是由操作系统来分配的,也就是由软件来设定的。而像加法溢出这样的异常代码,则是由 CPU 预先分配好的,也就是由硬件来分配的。这又是另一个软件和硬件共同组合来处理异常的过程。

    拿到异常代码之后,CPU 就会触发异常处理的流程。计算机在内存里,会保留一个异常表(Exception Table)。也有地方,把这个表叫作中断向量表(Interrupt Vector Table),好和上面的中断向量对应起来。

 

     CPU 在拿到了异常码之后,会先把当前的程序执行的现场,保存到程序栈里面,然后根据异常码查询,找到对应的异常处理程序,最后把后续指令执行的指挥权,交给这个异常处理程序。

8、异常分类:中断、陷阱、故障和中止

    第一种异常叫中断(Interrupt)。顾名思义,自然就是程序在执行到一半的时候,被打断了。这个打断执行的信号,来自于 CPU 外部的 I/O 设备。在键盘上按下一个按键,就会对应触发一个相应的信号到达 CPU 里面。CPU 里面某个开关的值发生了变化,也就触发了一个中断类型的异常。

 

    第二种异常叫陷阱(Trap)。陷阱,其实是程序员“故意“主动触发的异常。就好像你在程序里面打了一个断点,这个断点就是设下的一个"陷阱"。当程序的指令执行到这个位置的时候,就掉到了这个陷阱当中。然后,对应的异常处理程序就会来处理这个"陷阱"当中的猎物。

 

    第三种异常叫故障(Fault)。它和陷阱的区别在于,陷阱是开发程序的时候刻意触发的异常,而故障通常不是。比如,在程序执行的过程中,进行加法计算发生了溢出,其实就是故障类型的异常。这个异常不是我们在开发的时候计划内的,也一样需要有对应的异常处理程序去处理。

    故障和陷阱、中断的一个重要区别是,故障在异常程序处理完成之后,仍然回来处理当前的指令,而不是去执行程序中的下一条指令。因为当前的指令因为故障的原因并没有成功执行完成。

    最后一种异常叫中止(Abort)。与其说这是一种异常类型,不如说这是故障的一种特殊情况。当 CPU 遇到了故障,但是恢复不过来的时候,程序就不得不中止了。

 


 


posted @ 2020-03-18 21:18  庞某人  阅读(7916)  评论(0编辑  收藏  举报