设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

CPU流水线的探秘之旅

2013-6-6 14:19| 发布者: 红黑魂| 查看: 5596| 评论: 0|来自: 伯乐在线

摘要:   英文原文:A Journey Through the CPU Pipeline   编译:@deuso_ICT来自:伯乐在线  作为程序员,CPU 在我们的工作中扮演了核心角色,因此了解处理器内部的工作方式对程序员来说不无裨益。  CPU 是如何工 ...

  这个现象被称为流水线阻塞或者流水线气泡。

  另外一个关于流水线的问题是有些指令执行速度快,有些指令执行速度慢。这个问题在奔腾处理器的双流水线架构下显得更加明显。

  奔腾 Pro 拥有 12 级流水线。当这个数字被首次宣布后,所有的程序员都倒抽了一口气,因为他们知道超标量流水线是如何工作的。如果 Intel 仍然按照以前的思路设计超标量流水线的话,流水线的阻塞和执行速度慢的指令会严重影响执行速度。但同时,Intel 宣布了完全不同的流水线设计,叫做乱序执行部件(Out-of-Order core)。单从叙述上很难理解这些改变带来的好处,但 Intel 确信这些改进是令人激动的。

  让我们来更深入的看看这个乱序执行的部件吧!

  乱序执行流水线

  在描述乱序执行流水线时,往往是一图胜千言。所以我们主要以图例进行介绍。

  CPU 流水线图例

  I486 处理器拥有 5 级流水线。这种设计在现实世界中的其他处理器中很常见,而且效率不错。

  而奔腾处理器的流水线比 i486 更好。两条流水线可以并行运行,而且每条流水线可以同时有多条指令在不同流水级执行。它几乎可以同时执行比 i486 多一倍的指令。

  能够快速完成的指令需要等待前面执行慢的指令即使在并行流水线中也仍然是一个问题。流水线仍然是线性的,导致处理器面临性能瓶颈难以逾越。

  乱序执行部件和之前处理器设计中的线性通路有很大不同,它增加了一些复杂度,引入了非线性的通路。

  第一个改变是指令从内存中取到处理器的指令缓存的过程。现代处理器能够检测何时会产生一个大的分支跳转(比如函数调用),然后提前将跳转目的地的指令加载到指令缓存中。

  译码级有一些略微的修改。不同于以往处理器仅仅译码指令指针指向的指令,奔腾 Pro 处理器每一个时钟周期最多能译码 3 条指令。现今的处理器(2008-2013 年)每个时钟周期最多可以译码 4 条指令。译码过程产生很多小片的操作,被称作微指令(micro-ops, µ-ops)。

  下一级(或者好几级)被称为微指令翻译,接着是寄存器重命名(register aliasing)。许多操作同时执行,并且执行的顺序是乱序的,所以有可能出现一条指令读一个寄存器的同时,另外一条指令正在对这个寄存器进行写操作。在处理器内部,这些原始的寄存器(如 AX,BX,CX,DX 等)被翻译(或者重命名)成为内部的寄存器,而这些寄存器对程序员是不可见的。寄存器和内存地址需要被映射到一个临时的地方用于指令执行。当前每个始终周期可以翻译 4 条微指令。

  当微指令翻译完成后,它们会进入一个重排序缓存(Reorder Buffer, ROB),ROB 可以存储最多 128 条微指令。在支持超线程的处理器上,ROB 同样可以重排来自两个虚拟处理器的指令。两个虚拟处理器在 ROB 中将微指令汇集到一个共享的乱序执行部件中。

  这些微指令已经准备好可以执行了。它们被放在保留站中(Reservation Station, RS)。RS 最多可以同时存储 36 条微指令。

  现在才开始乱序执行部件神奇的部分。不同的微指令在不同的执行单元中同时执行,而且每个执行单元都全速运行。只要当前微指令所需要的数据就绪,而且有空闲的执行单元,微指令就可以立即执行,有时甚至可以跳过前面还未就绪的微指令。通过这种方式,需要长时间运行的操作不会阻塞后面的操作,流水线阻塞带来的损失被极大的减小了。

  奔腾 Pro 的乱序执行部件拥有 6 个执行单元:两个定点处理单元,一个浮点处理单元,一个取数单元,一个存地址单元,一个存数单元。这两个定点处理单元有所不同,一个能够处理复杂定点操作,一个能同时处理两个简单操作。在理想状况下,奔腾 Pro 的乱序执行部件可以在一个时钟周期内执行 7 条微指令。

  现今的乱序执行部件仍然拥有 6 个执行单元。其中取数单元,存地址单元,存数单元没有变,另外 3 个多少发生了变化。这三个执行单元都可以执行基本算术运算,或者执行更复杂的微指令。但每个执行单元擅长执行不同种类的微指令,使得它们能更高效的执行运算。在理想状况下,现今的乱序执行部件可以在一个时钟周期内执行 11 条微指令。

  最终微指令会得到执行,在经过数个流水级之后,最终会退出流水线。这时,这条指令完成并且递增指令指针。但从程序员的角度来说,指令仅仅是从一端进入 CPU,从另一端退出,就像老的 8086 一样。

  如果你仔细看过上面的内容,你会注意到上面提到过很重要的一个问题:如果执行指令的位置发生了跳转会发生什么?例如,当指令运行到”if”或者是”switch”时,会发生什么呢?在较老的处理器中这意味着清空流水线,等待新的跳转目的指令的取指执行。

  当 CPU 指令队列中存储了超过 100 条指令时,发生流水线阻塞带来的性能损失是极其严重的。所有的指令都需要等待跳转目的的指令取回并且重启流水线。在这种情况下,乱序执行部件需要将跳转指令之后但是已经执行的微指令全部取消掉,返回到执行前的状态。当所有乱序执行的微指令都退出乱序执行部件之后,将它们丢弃掉,然后从新的地址开始执行。这对于处理器来说是相当困难的,而且发生的频率很高,因此对性能的影响很大。这时,引入了乱序执行部件的另外一个重要功能。



酷毙
2

雷人

鲜花

鸡蛋

漂亮

刚表态过的朋友 (2 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部