为什么在“ if-else”语句中将最可能的条件放在首位?

Sea*_*her 5 language-agnostic if-statement

我经常听到这样的声音,足以真正质疑它-许多人说,如果是,否则就应该把最有可能成立的条件放在首位。因此,condition大多数情况下,如果if 可能为假,则放入!conditionif语句,否则使用condition。我的意思的一些虚构插图:

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

if (!unlikely) {
    // do this
} else {
    // do that
}
Run Code Online (Sandbox Code Playgroud)

有人说这是更有效的方法-也许是由于分支预测或其他优化方法,我从未真正询问过何时违反该主题-但据我所知,总是会有一个测试,并且两条路径都可以导致跳跃。

因此,我的问题是-是否存在令人信服的理由(“令人信服的理由”可能会带来很小的效率提高),为什么最可能为真的条件应该在if-else语句中排在首位?

Ale*_*kov 4

顺序可能很重要有两个原因:

  1. 由于数据分布已知,多个 if/else_if/else_if/else 语句的多个分支具有不同的概率

样品-分类苹果,大多数是好的黄色(90%),但有些是橙色(5%),有些是其他颜色(5%)。

 if (apple.isYellow) {...}
 else if (apple.isOrange) {....}
 else {...}   
Run Code Online (Sandbox Code Playgroud)

 if (!apple.isYellow && !apple.isOrange) {...}   
 else if (apple.isOrange ) {....}
 else  {...}
Run Code Online (Sandbox Code Playgroud)

在第一个样本中,90% 的苹果只进行了一次 if 检查,10% 会进行 2 次检查,但在第二个样本中,只有 5% 进行了一次检查,95% 进行了两次检查。

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

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

  1. 低级 CPU 优化可能有利于其中一个分支(这更多的是关于传入数据一致地达到同一条件分支)。

与顺序执行代码的情况相比,如果执行条件跳转,早期/更简单的 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: 
    ....
Run Code Online (Sandbox Code Playgroud)

现代 CPU 不应该有这个问题,因为它们会解析两个分支的命令。他们甚至有条件的分支预测逻辑。因此,如果条件主要以一种方式解决,CPU 将假设条件将以特定方式解决,并在检查完成之前开始执行该分支中的代码。据我所知,在当前的 CPU 上,无论是条件的第一个分支还是备用分支都无关紧要。查看为什么处理排序数组比处理未排序数组更快?有关这方面的好信息。