分支预测:避免"else"分支进行简单操作会使代码更快(Java 示例)?



选项 1:

  boolean isFirst = true;
  for (CardType cardType : cardTypes) {
    if (!isFirst) {
      descriptionBuilder.append(" or ");
    } else {
      isFirst = false;
    }
    //other code not relevant to this theoretical question
  }

选项 2:

boolean isFirst = true;
for (CardType cardType : cardTypes) {
  if (!isFirst) {
    descriptionBuilder.append(" or ");
  } 
  isFirst = false;
  //other code not relevant to this theoretical question
}

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

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

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

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

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

我错过了什么吗?

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

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

使用 JMH 给出以下数字,大小为 10 的 cardTypes 数组和整数增量作为逻辑(Java 15/AMD 3950X/Windows 10):

Benchmark          Mode  Cnt          Score         Error  Units
Benchmark.option1  thrpt   25  273369417.720 ± 1618952.179  ops/s
Benchmark.option2  thrpt   25  273415784.192 ±  852618.585  ops/s

"选项 2"的平均性能提高了约 0.017% (YMMV)。

另请参阅:分支预测、方法调度、内存访问、吞吐量和延迟、垃圾回收。

代码具有相同的效果,但不会产生相同的字节代码或程序集(可能)。

这在性能方面有多大差异尚不清楚,并且可能是微不足道的。

更重要的是代码的清晰度。 由于在这样的简单情况下,由于代码更难推理,我看到了更多的错误和性能问题。

简而言之,对

你来说最清晰和最简单的东西也可能足够快,或者最容易修复。

不同的硬件对每个汇编程序指令都有不同的成本,在现代硬件上,由于流水线和缓存的影响,甚至指令的成本也很难预测。

从您的孤立示例中不清楚流水线和缓存上的 if 和 if/else 之间的区别。 如果您运行过一次该代码,则根本不可能看到任何差异。 在紧密循环中反复运行它,if 本身的性能将由 a) 检查成本和 b) 检查结果的可预测性主导。 换句话说,分支预测将成为主导因素,并且不会受到if或if/else代码块的影响。

关于分支预测效果的精彩讨论可以在这里阅读 为什么处理排序数组比处理未排序数组更快?(请参阅最高评分答案)。

假设您的代码片段是 for 循环中的 if 块。 Hotspot 具有展开循环的能力,这包括进行常见的"是循环的第一次迭代"检查并将其内联到循环之外。 从而避免了在每次循环迭代时重新检查条件的成本。 从而避免关注哪个更快,如果或如果/否则。

Oracle 在此处记录了此行为

两个代码具有相同的语义。

否 两个代码不同,

第一个代码应用isFirst = false;将标志设置为 false,如果你的条件不匹配if (!isFirst)

第二次代码每次更改您的标志false甚至满足条件。

if/else构造中有两个分支:顶部的条件分支和if部分末尾的else部分周围的分支。else部分没有分支,至少在任何中等能力的编译器中都没有分支。

与此相反,您必须平衡始终执行isFirst = false;行的成本。

在您提到的特定情况下,与方法调用的成本相比,它不太可能产生丝毫差异。

相关内容

  • 没有找到相关文章

最新更新