问题标签 [branch-prediction]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
670 浏览

cpu-architecture - 为什么要预测一个分支,而不是简单地并行执行两者?

我相信在创建 CPU 时,如果选择了错误的分支,分支预测会大大减慢速度。那么,为什么 CPU 设计人员会选择一个分支,而不是简单地执行两个分支,然后在确定选择了哪个分支后将其切断呢?

我意识到这只能在少量指令中深入 2 或 3 个分支,或者并行阶段的数量会变得非常大,所以在某些时候你仍然需要一些分支预测,因为你肯定会遇到更大的分支,但是像这样的几个阶段没有意义吗?在我看来,它会显着加快速度,并且值得增加一点复杂性。

即使只有一个分支深,几乎一半的时间都会被错误的分支吃掉,对吧?

或者也许它已经有点像这样了?当您开始组装时,分支机构通常只会在两个选择之间进行选择,对吗?

0 投票
1 回答
139 浏览

c - 为什么这个带有位运算符的语句与这个 if 语句相同?

我正在阅读这个问题为什么处理排序数组比处理未排序数组更快?以及 Mysticial 提供的最佳答案。答案很好地解释了正在发生的事情以及原因,并且还说:

那么可以做些什么呢?

如果编译器无法将分支优化为条件移动,如果您愿意牺牲可读性来换取性能,您可以尝试一些技巧。

代替:

和:

这消除了分支并用一些按位操作替换它。

这段代码到底在做什么,为什么它是等价的?

0 投票
2 回答
1419 浏览

c - “goto”语句如何影响 CPU 的“分支预测”?

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

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

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

我认为这可能是真的。

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

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

你知道吗?

0 投票
0 回答
338 浏览

assembly - 如何使用 2 位预测器预测无条件分支?

我发现:

(珊迪大桥)

间接跳转和调用的模式识别

间接跳转和间接调用(但不是返回) 使用与分支指令相同的两级预测器进行预测

在第 27 页:

http://www.agner.org/optimize/microarchitecture.pdf

我不明白条件分支和无条件分支如何都可以使用 2 位预测器?我认为无条件分支会使用分支目标缓冲区 (BTB)。如何使用 2 位预测器预测无条件分支?!

有人可以解释一下,比如最近的英特尔 CPU,分支预测如何在预测变量、历史表和 BTB 缓存方面适用于条件和无条件分支?我不确定它们是否一起工作,对于两种类型的分支,或者它们都存在但只处理不同的分支类型?

0 投票
0 回答
37 浏览

architecture - 哪些处理器更好?

为什么计算机架构师更关注动态无序处理器的分支预测器的准确性,而不是简单的 5 级有序处理器的分支预测器?

0 投票
6 回答
1273 浏览

java - 分支预测:避免简单操作的“else”分支是否会使代码更快(Java 示例)?

选项 1:

选项 2:

我的分析:两个代码具有相同的语义。

第一个代码)我不确定这段代码是有两个分支(就分支预测器而言)还是一个分支。我正在查看http://en.wikipedia.org/wiki/X86_instruction_listings但无法弄清楚是否有一个 X86 指令类似于“如果先前的条件值是假跳转那里”,以避免两个分支预测(非常糟糕)

第二个代码)最有可能总是执行简单的 MOV(寄存器或元素很可能已经在缓存中),这是相对便宜的(最多几个周期)

所以,我的观点是,除非处理器解码成微码指令可以做一些智能的事情或存在 X86 指令以避免必要的分支预测,否则第二个代码更快。

我知道这纯粹是理论上的问题,因为在实践中,这个分支可以使应用程序更快 0.000000002% 或类似的东西。

我错过了什么?

编辑:我添加了一个循环,为有问题的分支提供更多“权重”

EDIT2:问题是关于分支预测的英特尔架构(奔腾和更新的处理器)。

0 投票
2 回答
211 浏览

c++ - 分支预测的加速是否取决于谓词的复杂性?

假设我有一些函数IsTrue()返回一个bool. 如果程序员决定IsTrue()通常会返回true,她可能会使用 GCC__builtin_expect或类似的东西来加速那些典型情况下的指令。

举以下2个例子:

假设这IsTrue是不平凡的,这些之间有什么区别吗?放在参数列表中是否IsTrue()会导致在知道结果之前__builtin_expect评估指令缓存,还是仅在计算结果之后才应用分支预测?IsTrueIsTrue

0 投票
0 回答
98 浏览

assembly - 流行的处理器是否已知会“优化掉”分支到下一条指令的指令?

我正在查看 Visual Studio 中某些程序的反汇编,并查看以下内容:

这段代码只是愚蠢的。如果jae导致条件跳转控制传递到完全相同的指令,否则它将失败。

问题是 CPU 中的分支预测将如何处理它。CPU 会预测它应该“跳跃”还是“跌倒”。直到他们收集了一些关于之前执行代码的统计数据,英特尔 x86 处理器预测条件跳转为“不会完成”。所以这jae将被预测为“不会发生,失败”并且CPU将选择“失败”路径。

如果发生错误预测(结果是错误地选择了“失败”路径),CPU 应该正式重置管道并运行“分支”路径。

这里的诀窍是“失败”和“分支”有效地做同样的事情并且等同于nop.

我从未在任何有关分支的文档中看到过这种情况的分析。

流行的 CPU 通常可以将其jae视为nop或将使用通常的预测逻辑吗?

0 投票
0 回答
101 浏览

visual-c++ - 哪些开关/选项强制 CL(Microsoft C/C++ 编译器)生成“碎片化”过程?

在大多数情况下,编译过程是一堆处理器指令,它们在代码段中占据连续的字节范围。它当然可能包含有条件的和无条件的跳转以及非线性执行流程,但是查看反汇编列表,您可以明确地说出程序的开始(即入口点)在哪里以及程序在哪里结束。

但是,有时 CL 将过程拆分为多个部分并将这些部分混合在一起,以便您可以在proc_a的前半部分和proc_a的后半部分之间获得proc_b

问题是:什么命令行开关使编译器生成如下所述的代码。

我正在我的调试器/反汇编器中分析一个可执行文件,并注意到大量具有碎片化主体的函数。我有二进制文件本身,它的调试符号,我知道它是使用 CL 编译的,但我没有源代码,makefile,因此我不知道使用什么命令行选项来编译它。

让我给你看一个小例子(它只是一个演示代码,不是来自现实生活)。

假设您有以下用 C++ 编写的函数(boo是类,方法是virtual):

现在正在使用一些神秘的命令行选项运行,CL 决定取一小部分指令(表示return 0;条件分支)并将其移向远离 foo 过程基本部分边界的代码段末尾。此外,这小部分指令将在调试符号表中有自己的条目,其名称由被拆分的过程名称、下划线字符和十进制数组成(在大多数情况下,但不是在所有情况下)跳转指令中相对于过程入口点(例如 foo_13)的跳转目标的偏移量(它本身就是偏移量)。

因此,CL编译如下:

foo_X(X 代表如上所述的某个十进制数)是一个小的两指令块,表示 if 语句的真分支。

就我而言,有一大堆这样的小块。它们中的大多数(但不是全部)是两条指令的(通过重置某些寄存器xor reg, reg并跳回函数的主要部分,或者将 EAX 归零并执行 RETN)。它们在调试符号表中都有自己的名称。如果我们有foobarbaaz 之类的函数,那么还有foo_7bar_22bar_43baaz_19。大多数这些小块被组合在一起,并在代码部分中彼此靠近,但远离它们的对应部分(foo,bar,baaz),因此到这些块的跳转遍及代码部分。


它可能与基于分支预测的优化有关:编译器将它认为不太可能发生的执行分支移离基本执行流路径。但是,我在 1998 年编译的二进制文件中观察到了这些技巧,因此很明显,使用了来自 MSVC6(甚至是 MSVC5!)的 CL.EXE,并且没有办法向那些旧版本的优化器提供有关分支预测的提示CL。是的,现代版本的 CL 支持profile-guided optimization,但我们谈论的是 1998 年编译的代码。

我正在寻找的选项之一是/Gy - 一个所谓的功能级链接选项。此选项指示编译器将每个单独的函数包装到单独的 COMDAT 中,以便在链接时可以以任何所需的顺序重新排序函数,并且可以排除其中的一些函数。但是,据我所见,它将整个函数包装到单个 COMDAT 中,但就我而言,它需要将单个函数的单独片段放入单独的 COMDAT 中,以 (1) 允许链接器将函数片段放置在很远的地方彼此和(2)允许这样的小片段在调试符号表中拥有自己的名称。

再一次,我的问题是 CL/LINK 的哪些命令行选项/开关控制这种行为。

0 投票
3 回答
79 浏览

c++ - 最小化函数选择和函数调用开销?

我有一个大数组(图像),我需要对该数据进行许多小的可配置计算。我将在这里发布一个示例。 注意:这不是实际问题,而是我需要做的最小/希望说明性示例。

在我的代码中,将循环放在每个函数内部是没有意义的。

但是,param1 和 param2 在循环期间保持不变,并且它们在编译时是已知的。

有没有办法消除 if/elseif 语句的影响?