为什么将最可能的条件放在`if-else`语句中?

时间:2014-11-27 21:58:50

标签: if-statement language-agnostic

我经常听到这个问题,实际上对它提出质疑 - 许多人说,在if-else声明中,应该首先考虑最有可能真实的条件。因此,如果condition在大多数情况下可能都是假的,请将!condition放在if语句中,否则使用condition。一些人为的说明我的意思:

if (likely) {
    // do this
} else {
    // do that
}

if (!unlikely) {
    // do this
} else {
    // do that
}

有些人说这更有效率 - 可能是由于分支预测或其他一些优化,我从未真正询问过什么时候这个话题遭到破坏 - 但据我所知,总会有一个测试,并且这两条路径都会导致跳跃。

所以我的问题是 - 是否有一个令人信服的理由(“令人信服的理由”可能是一个微小的效率增益)为什么最有可能真实的条件应该首先出现在if-else语句中?

1 个答案:

答案 0 :(得分:4)

订单可能有两个原因:

  1. 由于已知的数据分布,多个if / else_if / else_if / else语句的多个分支具有不同的概率
  2. 样品 - 分类苹果,大多数是黄色一次(90%),但有些是橙色(5%),有些是其他颜色(5%)。

     if (apple.isYellow) {...}
     else if (apple.isOrange) {....}
     else {...}   
    

    VS

     if (!apple.isYellow && !apple.isOrange) {...}   
     else if (apple.isOrange ) {....}
     else  {...}
    

    在第一个样本中,90%的苹果只检查了一个苹果,10%检查了2个,但在第二个样本中,只有5%检查了一个支票,95%命中了两个。

    因此,如果您知道在使用一个分支的机会之间存在显着差异,那么将其移动到第一个条件可能是有用的。

    请注意,您的单个if样本在该级别上没有任何区别。

    1. 可能有利于其中一个分支的低级别CPU优化(此外,这更多地是关于传入数据以始终如一地达到相同的条件分支)。
    2. 与顺序执行代码的情况相比,如果执行条件跳转,早期/更简单的CPU可能需要清除命令解析管道。所以这可能是提出这种建议的原因。

      样品(假装配):

          IF R1 > R2 JUMP ElseBranch
          ADD R2, R3 -> R4  // CPU decodes this command WHILE executing previous IF
          ....
          JUMP EndCondition  
      ElseBranch:    
          ADD 4, R3 -> R4   // CPU will have to decodes this command AFTER
                            // and drop results of parsing  ADD R2, R3 -> R4  
          ....
      EndCondition: 
          ....
      

      现代CPU应该没有问题,因为它们会解析两个分支的命令。它们甚至具有条件的分支预测逻辑。因此,如果条件主要通过单向解决,CPU将假定条件将以特定方式解析,并在检查完成之前开始在该分支中执行代码。据我所知,当前CPU无论是第一个还是备用条件分支都无关紧要。查看Why is it faster to process a sorted array than an unsorted array?了解相关信息。