c++ - 在 C++ 中,分支预测器是否预测隐式条件语句?
问题描述
在这段代码中,它是result += runs[i] > runs[i-1];
一个隐式条件语句。在 C++ 中,分支预测器是否对此语句进行预测?还是我必须明确使用if
关键字才能进行分支预测?
using namespace std;
int progressDays(vector<int> runs) {
if (runs.size() < 2) {return 0;}
int result = 0;
for (int i = 1; i < runs.size(); i++) {result += runs[i] > runs[i-1];}
return result;
}
解决方案
CPU 不直接运行 C++,它们运行机器代码。所以答案取决于你的 C++ 如何编译成汇编/机器代码。 您在 C++ 中表达程序逻辑的选择只会间接影响这一点。现代编译器可以并将 C++if()
语句的 if 转换为没有分支的 asm(也称为无分支)。(对于 GCC,这-O3
比 at更积极地完成-O2
- 请参阅gcc 优化标志 -O3 使代码比 -O2 慢)
在大多数架构中,有一些有效的方法可以直接将比较结果转换为 0 或 1 整数。(或以不同的方式无分支地递增,甚至更直接,例如AArch64 的csinc
//指令进行条件递增,读取输入寄存器和标志) csel
。所以通常使用整数值将无分支编译。cinc
x < y
int conditional_inc(int x, int y, int z) {
z += (x<y);
return z;
}
# x86-64 clang -O3
conditional_inc(int, int, int)
xor eax, eax # prepare a zeroed register for setl of the low byte, to extend to 32-bit. (x86 is annoyingly clunky and inefficient at this)
cmp edi, esi
setl al # EAX = AL = (x<y) signed compare
add eax, edx # EAX += z in the retval register
ret
AArch64 效率更高,组合增量和选择指令替换 xor-zero/setcc/add。
conditional_inc(int, int, int):
cmp w0, w1 // compare
cinc w0, w2, lt // use the flags result, and the other 2 inputs.
ret
所有这些,如 x86-64 setcc
,只是 ALU 指令,而不是控制(程序计数器没有条件更改),因此具有数据依赖性而不是控制依赖性,因此不需要分支预测,因为没有分支。(最著名的此类指令可能是 x86 cmovcc
,但在这种情况下只setcc
需要)
- CMOVcc 是否被视为分支指令?
- 为什么条件移动不易受到分支预测失败的影响?显示了使用 cmov 有条件地递增的 asm 示例。
通常,比较与分支是分开的。您可以进行比较,然后得到一个没有分支的布尔值。(分支确实需要一些东西来分支,但这可以是与整数或布尔值的零的隐式比较。)
所以这不是一个条件语句,它只是一个用作整数的布尔值。
推荐阅读
- python - 即使我将 pytest.py 移动到 /bin,也找不到命令“pytest”
- yii - yii2 使用会话从 yii 获取用户身份验证
- excel - excel显示链接单元格的单元格地址NOT值
- javascript - 为复杂的验证编写正则表达式
- java - Java中的金字塔模式,星号后跟下划线
- cumulocity - 如何使用 c8y 中的事件处理脚本在数据资源管理器图形模式表中显示自定义信息
- git - 如何将 git 分支获取到先前的提交并将其作为新的 HEAD 推送?
- swift - 快速词典:地图中的地图
- laravel - Laravel MultiAuth 已登录,但将我视为访客
- python - shape(150,) 和 shape (150,1) 有什么区别?