延迟槽有什么意义?

时间:2013-03-13 00:50:22

标签: assembly mips pipelining

因此,根据我对延迟槽的理解,它们在调用分支指令时发生,并且分支之后的下一条指令也从内存加载。这有什么意义?在分支被采取的情况下,你不希望分支后的代码不运行吗?是否节省时间,以防分支机构没有被采取?

我正在查看管道图,看来分支后的指令仍在执行..

5 个答案:

答案 0 :(得分:21)

如今大多数处理器都使用管道。 H& P书中的想法和问题随处可见。在那些原始着作的时候,我会假设实际的硬件与管道的特定概念相匹配。获取,解码,执行,回写。

管道基本上是一条装配线,该生产线有四个主要阶段,因此您最多只能同时处理四条指令。这混淆了执行指令需要多少时钟的概念,它需要多个时钟,但如果你有一些/多个并行执行,那么“平均”可以接近或超过每个时钟一个。

虽然装配线失败,但是当你采取分支时。必须抛出提取和解码阶段中的指令,并且必须再次开始填充,因此您需要几个时钟来获取,解码,然后再执行。分支阴影或延迟槽的想法是恢复其中一个时钟。如果声明分支之后的指令总是被执行,那么当执行分支时,解码槽中的指令也会被执行,取指槽中的指令被丢弃,你有一个时间空洞而不是两个。因此,不是执行,清空,清空,执行,执行,而是在管道的执行阶段执行,执行,清空,执行,执行....分支的痛苦减少50%,整体平均执行速度提高等等。

ARM没有延迟槽,但它通过声明程序计数器是前面的两条指令,也给出了管道的错觉。任何依赖于程序计数器(pc相对寻址)的操作必须使用前面两条指令的pc计算偏移量,对于ARM指令,这对于原始拇指4字节是8字节,当你添加thumb2指令时它会变得混乱。

这些是学术界之外的幻想,管道更深,有很多技巧等,以便遗留代码继续工作,和/或不必重新定义指令如何适用于每个架构的变化(想象mips rev x,1个延迟槽,rev y 2个延迟槽,如果条件a则转3个槽,如果条件b则转2个槽,如果条件c则处理1个槽)处理器继续执行分支后的第一个指令,并丢弃在重新填充管道之后,另一把或者十几个。管道的实际深度通常不会与公众分享。

我看到有关这是一个RISC的评论,它可能已经开始,但是CISC处理器使用相同的技巧,只是给出传统指令集的错觉,有时CISC处理器只不过是一个RISC或者带有包装器的VLIW内核,用于模拟传统的CISC指令集(微编码)。

观看它制作的节目。可视化装配线,该行中的每个步骤都有一个任务。如果生产线中的一个步骤用尽了蓝色,并且要制作蓝色和黄色产品,那么你需要蓝色的东西。你不能再换一个新的蓝色星期,因为有人搞砸了。因此,您必须停止生产线,将耗材更改为每个阶段,并将红色和绿色产品暂时生产,这通常可以在不倾倒生产线的情况下正确分阶段进行。这就像一个分支,在装配线深处的某个地方发生的事情,导致线必须改变,转储线。延迟槽是一种恢复一个产品必须在生产线中丢弃的方法。在生产线停止之前,N + 1产品不再出现,而是在每次生产运行中出现N + 1产品。代码的执行就像生产运行的爆发一样,在命中分支到另一个短执行路径之前,你经常得到短的,有时很长的线性执行路径,分支另一个短的执行路径......

答案 1 :(得分:11)

  

在分支被采取的情况下,您不希望分支后的代码不运行吗?

但现在已经太晚了。 CPU管道的整个目的是您希望在每个周期完成一条指令。实现这一目标的唯一方法是每个周期获取一条指令。因此,在CPU注意到必须采取分支之前,分支指令之后的代码已经被提取并且正在进行中。

  

这有什么意义?

没有意义。它不是一个特征,它只是这种管道设计的一种神器。

答案 2 :(得分:7)

即使指令出现在分支之后的程序中,它实际上也会在分支被执行之前运行。查看有关delay slotbranch hazard

的维基百科页面

答案 3 :(得分:6)

RISC架构的想法是简化解码并优化流水线以提高速度。 CPU尝试通过流水线操作重叠指令执行,因此一次执行多条指令。

延迟时隙的要点特别是执行一条已通过管道的一部分的指令,现在位于一个只需要丢弃的插槽中。

优化器可以在分支目标处获取第一条指令并将其移至延迟槽,使其执行并且#34;免费"。

该功能并没有成为主流,主要是因为世界标准化了现有的ISA 1 设计,即x86和x86-64,但也出于另一个原因。

晶体管数量的二次爆炸使非常复杂的解码器成为可能。无论如何,当架构上可见的ISA被转换为微操作时,像延迟槽这样的小黑客变得不重要。

<小时/> 1。 ISA:指令集架构

答案 4 :(得分:5)

在流水线实现的教科书示例中,CPU 提取解码执行写回 。这些阶段都发生在不同的时钟周期中,因此实际上,每个指令在4个周期内完成。然而,当第一个操作码即将被解码时,下一个操作码将从内存中加载。当CPU完全占用时,同时处理4个不同指令的部分,CPU的吞吐量是每个时钟周期一个指令。

在机器代码中有一个序列:

      sub r0, #1
      bne loop
      xxx

处理器可以将来自sub r0, #1回写阶段的信息反馈到bne loop执行阶段,但同时xxx已经处于 fetch 阶段。为了简化展开管道的必要性,CPU设计人员选择使用延迟槽。在获取延迟时隙中的指令之后,获取单元具有分支目标的适当地址。优化编译器很少需要在延迟槽中放置NOP,但在两个可能的分支目标上都必须插入一条指令。