C++ 条件运算符性能

C++ Conditional operator performance

本文关键字:性能 条件运算符 C++      更新时间:2023-10-16

我有一个条件语句expensive_foo()在99.9%的情况下是错误的。我有一个条件语句bar在~50%的情况下是正确的。

如果这两个陈述都是正确的,我希望采取一些行动。所以我几乎肯定知道expensive_foo()是假的,只有当bar是真的时,我才想检查它。

下面的代码会仅在bar为真时才检查expensive_foo()吗?还是每次都会检查expensive_foo()

if ( bar && expensive_foo() )
{
    ...
}

或者我需要做一个这样的结构:

if ( bar )
{
    if ( expensive_foo() )
    {
        ...
    }
}
逻辑

AND 运算符&&短路,这意味着当且仅当第一个操作数被计算为 true 时,可以保证第二个操作数被计算。条件if (bar && foo)if (bar) if (foo)是相同的。

鉴于foo的计算成本很高,您几乎肯定应该先检查bar。尽管分支预测器不能很好地预测bar,但与foo计算相比,这是一个很小的影响。

因此,结构可能应该是:

if (bar)
{
    if (bool const foo = compute())   // expensive
    {
        // ...
    }
}

请注意,所有这些结构都意味着我们可能会也可能不会调用compute()。如果你需要无条件调用函数,那么你应该把它作为第一个检查。在这种情况下,应该利用对结果的成功分支预测。

两个代码只有在bar为真的情况下才会检查foo。在第一种情况下,这是由语言惰性布尔表达式计算来保证的(实际上在某些编译器中可以显式关闭,但默认情况下为 ON)。

其他答案很好,但我质疑这个前提。

如果您查询的谓词在 99.9% 的时间内为 false,这类似于在包含 2000 个条目的列表中执行线性搜索,其中您要查找的项目可能位于概率大致相等的任何位置。

在这种情况下,通常会尝试以不同的方式组织列表,以便进行O(logN)(或更好的)搜索而不是O(N)。我不知道你是否能做到这一点,但这就是我要关注的地方。

当一个问题以高度偏斜的概率被问到时,如果可以消除它,这可能是一个很大的加速机会。(假设大部分时间都花在了这项活动上。如果没有,这一点就没有意义了。

如果两者的优化程序集不完全相同,我会感到惊讶。 如果 bar 为 false,则永远不会调用 expensive_foo()。

我看到一条评论说编译器可以重新排序操作,我倾向于这种观点。改进顺序程序自动并行化的努力导致了更好的编译器,它可以帮助程序员避免从他们的程序中使用复杂的并行化例程。编译器可以对操作进行重新排序,前提是重新排序不会违反/恶化局部性,或者在广义上不违反程序的实际意图。

但我怀疑编译器会尝试重新排序条件语句的事实喜欢:

  if ( bar && expensive_foo() )

如果将较便宜的布尔函数放在开头,可以肯定的是我们可以节省一些时间。