gpt4 book ai didi

performance - 分支预测变量与此同时起作用吗?

转载 作者:行者123 更新时间:2023-12-03 15:37:40 24 4
gpt4 key购买 nike

大多数(如果不是全部)现代处理器都使用一种称为“分支预测”的技术,通过这种技术,可以猜测在if-then-else分支中应该走什么路。

我在考虑该计划时有一个问题。假设我们有这段代码,没有特定的语言:

if(someCondition)
{
// some action
return someValue;
}
// some other action
return someOtherValue;

从逻辑上讲,该代码等效于以下代码:
if(someCondition)
{
// some action
return someValue;
}
else
{
// some other action
return someOtherValue;
}

分支预测器将在第二个示例中“预测”分支,但是第一个示例呢?会猜到吗?什么将被加载到管道中?无论使用哪个示例,而忽略块中实际代码的影响,都可以提高速度吗?

我的猜测取决于编译器:如果使用跳转实现语句(在汇编中),则只有在设置了寄存器中的比较标志时才执行跳转。现在,汇编指令的确切外观取决于编译器。除非每个编译器都有一种通用的处理方式(我怀疑是这样),否则这取决于编译器。在这种情况下,最新的Visual Studio C++和GC++编译器会发生什么?

正如hexafraction所指出的,返回值之间的关系以及 someCondition的确定方式……分支预测器可能不会起作用。让我们仅将true和false视为返回值。对于该条件,让我们假设它是一个在函数内部或外部,局部变量和一些算术语句已预先确定的字段。

老实说,我不认为条件是局部变量的情况与字段是在同一函数中预先确定的情况之间有很大区别的。

最佳答案

很有可能gcc -O3使用条件移动指令将其优化为无分支序列。例如在x86上

# generate someValue in %rax, the x86-64 ABI's return value register
# generate someOtherValue in %rdi, to pick one at random
test someCondition # probably actually test or cmp a register
cmovz %rdi, %rax # copy %rdi to %rax, if the zero flag is set.
ret

cmov的输入和标志都具有数据依赖关系。条件分支是控件依赖项。使用cmov通常是好的,除非它是一个较长的依赖链的一部分,并且分支是相当可预测的。

如果 if块中还有更多工作,gcc将生成条件跳转指令。
# generate someValue in %rax
test someCondition
jz .zero
ret
.zero:
# compute someOtherValue. This work doesn't need to happen at all
# if we don't end up needing it, unlike in the cmov case
mov someOtherValue, %rax
ret

分支预测对条件跳转指令起作用,而不对高级构造起作用。如果循环条件为真,则使用相同的指令跳回到循环的顶部。根据 http://agner.org/optimize/的说法,最近的Intel CPU记住最多可进行64次循环迭代的模式。因此,如果迭代次数为64或更少,则每次运行相同迭代次数的循环都不会在最后一次迭代中出现分支错误预测。

因此,分支预测器不会考虑指令序列来猜测是否将执行跳转。每条单独的分支指令在采用时都会在branch-history-buffer中获得一个条目。是的,每个编译器别无选择,只能使用 jcc(条件代码跳转)指令来实现分支/循环。

默认值为未预测。如果该预测是正确的,则CPU不会从缓存中逐出可能仍然有用的信息来腾出空间。有关更多底层细节,请参阅Agner Fog的microarch文档。

在Linux上,要查看实际的分支预测器,可以使用 perf stat:
perf stat /bin/ls  # in some big directory
... normal ls output

Performance counter stats for '/bin/ls':

10.403069 task-clock (msec) # 0.094 CPUs utilized
2,255 context-switches # 0.217 M/sec
0 cpu-migrations # 0.000 K/sec
190 page-faults # 0.018 M/sec
16,612,260 cycles # 1.597 GHz
7,843,399 stalled-cycles-frontend # 47.21% frontend cycles idle
5,205,565 stalled-cycles-backend # 31.34% backend cycles idle
20,227,093 instructions # 1.22 insns per cycle
# 0.39 stalled cycles per insn
3,975,777 branches # 382.173 M/sec
########### These two lines ######
55,785 branch-misses # 1.40% of all branches

0.110765717 seconds time elapsed

带有默认cpufreq调控器的低功耗时钟速度下的Intel Sandybridge(i5 2500k)在 ls完成之前不会提高时钟速度。

关于performance - 分支预测变量与此同时起作用吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31953538/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com