3

为了了解更多关于 CPU 和代码优化的信息,我开始学习汇编编程。我还阅读了有关 CPU 为加速自身而进行的“分支预测”之类的巧妙优化。

我的问题可能看起来很愚蠢,因为我还不太了解这个主题。

我有一个非常模糊的记忆,我在某处(在互联网上)读到过这些goto语句会降低程序的性能,因为它不适用于 CPU 中的分支预测。然而,这可能只是我编造的东西,并没有真正阅读过。

我认为这可能是真的。

我希望这个例子(在伪 C 中)能澄清我为什么这么认为:

int function(...) {
    VARIABLES DECLARED HERE

    if (HERE IS A TEST) {
        CODE HERE ...
    } else if (ANOTHER TEST) {
        CODE HERE ...
    } else {
        /*
        Let us assume that the CPU was smart and predicted this path.
        What about the jump to `label`?

        Is it possible for the CPU to "pre-fetch" the instructions over there?
        */
        goto label;
    }

    CODE HERE...

label:
    CODE HERE...
}

对我来说,这似乎是一项非常复杂的任务。这是因为 CPU 需要查找goto跳转到的位置,以便能够预取那里的指令。

你知道吗?

4

2 回答 2

7

无条件分支对于分支预测器来说不是问题,因为分支预测器不必预测它们。

它们为推测指令获取单元增加了一点复杂性,因为分支(和其他改变指令指针的指令)的存在意味着指令并不总是以线性顺序获取。当然,这也适用于条件分支。

请记住,分支预测和推测执行是不同的东西。您不需要分支预测来进行推测执行:您可以假设从未采用分支的情况下推测执行代码,并且如果您确实采用了分支,则取消该分支之外的所有操作。在无条件分支的情况下,这将是一件特别愚蠢的事情,但它会使逻辑保持良好和简单。(IIRC,这就是第一个流水线处理器的工作方式。)

(我猜你可以在没有推测执行的情况下进行分支预测,但实际上并没有什么意义,因为分支预测器没有人可以告诉它的预测。)

所以是的,分支——有条件的和无条件的——增加了指令获取单元的复杂性。没关系。CPU 架构师是一些非常聪明的人。

编辑:回到糟糕的过去,人们观察到goto语句的使用可能会对当时的编译器优化代码的能力产生不利影响。这可能是你想的。现代编译器要聪明得多,而且通常不会对goto.

于 2015-01-09T18:59:48.603 回答
2

由于“流水线”和类似活动,分支指令实际上可以放置在实际分支发生的位置之前的几条指令。(这是在编译器中找到的分支预测逻辑的一部分)。

goto 语句只是一个跳转指令。

附带说明:给定结构化编程概念、代码清晰度、可读性、可维护性考虑等;永远不要使用“goto”语句。

在大多数 CPU 上,任何跳转/调用/返回类型的指令都会刷新预取缓存,然后从新位置重新加载该缓存,如果新位置不在缓存中。

注意:对于总是包含“至少”一条跳转指令的小循环,许多 CPU 都有一个内部缓冲区,程序员可以利用该缓冲区使小循环只执行一个预取序列,因此执行速度要快很多数量级。

于 2015-01-09T18:56:09.853 回答