在现代计算机系统中,CPU的性能至关重要。然而,CPU在执行指令的过程中,常常会遇到一些"冒险"情况,即可能出现某些问题或冲突。为了提升指令吞吐量,也就是在固定时间段内执行更多的指令,CPU会主动进行一些"冒险"选择,这种策略被称为"hazard"。尽管这种策略有一定的风险,但是它也带来了机会,让CPU获得更高的处理效率。
接下来,我们就来深入探讨一下CPU中的这些黑科技:CPU冒险和预测。
结构冒险
首先,我们来看看结构冒险。结构冒险主要是由于硬件资源的竞争问题引起的,也就是说,当多个任务试图同时访问同一硬件资源时,就会出现访问冲突。
为了解决这个问题,我们可以采取增加资源的方式。比如在薄膜键盘中,多个键使用同一条线路,如果同时触发多个键,就会产生冲突。如果使用机械键盘,每个键都有一条独立的线路,就可以避免这种冲突。对于访问内存,只有一个地址译码器时,两条指令同时访问内存时也会冲突,此时可以在CPU缓存中区分指令缓存和数据缓存,这样就可以并发指令和数据的访问操作,降低冲突。
另一种解决办法是指令对齐,通过插入nop操作,使后一条指令的阶段一定不和前一个指令的相同阶段在同一个时钟周期执行,从而避免访问冲突。
数据冒险
其次,我们要解决的是数据冒险。数据冒险主要是由于程序需要按照顺序执行,否则结果会不正确;下一条指令常常依赖上一条指令的输出,这就导致了数据冒险的出现。
解决这个问题的一种方式是流水线停顿,通过插入停顿nop,保证依赖的之前流水线的某个阶段完成才执行本次流水线的某个阶段。
另一种方式是操作数前推(转发),这是通过使用电路旁路,不保存寄存器,直接转发给下一条指令,减少流水线停顿。
还有一种方法是乱序执行,取指令和指令译码仍保持级次顺序,在保证指令依赖的前提下,让多个指令执行尽可能并行,然后再对执行结果排序,保证指令的输出顺序。
控制冒险
最后,我们需要解决的是控制冒险。控制冒险主要是因为为了取到正确的指令,不得不延迟等待;条件跳转指令执行完成更新PC寄存器后,才能知道是顺序取下一条指令还是跳转到其它内存地址取指令。
解决这个问题的一种方法是缩短分支延迟,译码阶段就能通过电路旁路来执行条件运算,并将跳转地址写入到PC寄存器。
另一种方法是分支预测,做分支预测时,都是以不跳转作为下一步操作的默认选项,当状态机中统计的被打断次数达到3次,就会预测下条指令也是打断指令,从而减少因指令打断得抛弃之前的操作的overhead。
分支预测还可以分为静态预测和动态预测。静态预测是假装分支不发生,顺序取下一条指令并执行,预测错误需要一定的清除开销。动态预测则更为复杂,包括一级分支预测和双模态预测,用来记录连续分支比较情况,并进行预测。
最后我将这篇文章的内容总结为了一张思维导图,有兴趣的可以下载观看。 高清大图请关注微/信/公/众/号 "萤火架构",发消息"冒险与预测",即可获取。
总的来说,CPU冒险和预测,虽然有一定的风险,但是它极大地提高了CPU的执行效率,也展示了计算机技术的魅力。对于计算机技术开发人员来说,理解和掌握这些知识是非常重要的,它们将帮助我们设计出更好的程序,让程序的执行更有效率。