【问题标题】:efficient, extremely-unlikely conditionals?有效的,极不可能的条件?
【发布时间】:2014-11-30 20:33:26
【问题描述】:

我有一些性能关键代码会在极不可能的情况下崩溃和烧毁(例如,当中间 double 等于 0.0 时,该双精度值不太可能为零而不是任何其他值)。

当然,一种选择是吹口哨并忽略角落案例,并祈祷它永远不会出现。但如果可能的话,我想抓住它;另一方面,我不太热衷于将条件添加到性能关键代码中。添加表单检查有什么技巧吗

if(val == 0.0)
{
    // extremely unlikely code path
}

以某种方式将性能损失降至最低?在某些编译器上可以传递 CPU 分支预测提示,但我听说这些对现代处理器不再有任何影响?

【问题讨论】:

    标签: c++ performance


    【解决方案1】:

    使用可能,不太可能

    在Linux内核中,它们被定义为

    #define likely(x)       __builtin_expect(!!(x), 1)
    #define unlikely(x)     __builtin_expect(!!(x), 0)
    

    __builtin_expect 宏是使用分支预测的 GCC 特定宏;它们告诉处理器某个条件是否可能为真,以便处理器可以在分支的正确“一侧”预取指令。

    您应该将定义包装在 ifdef 中以确保在其他编译器上编译:

    #ifdef __GNUC__
    #define likely(x)       __builtin_expect(!!(x), 1)
    #define unlikely(x)     __builtin_expect(!!(x), 0)
    #else
    #define likely(x)       (x)
    #define unlikely(x)     (x)
    #endif
    

    【讨论】:

    • 不知道这个,v 有趣。你知道其他编译器的等价物吗?
    • 对于铿锵声也许你可以检查这个:llvm.org/docs/BranchWeightMetadata.html,顺便说一句,你使用的是什么编译器?
    • 此外,大多数流行的编译器都假定第一个分支是公共路径。根据我的经验,通过添加空的 if 语句来牺牲样式是不值得的,但它确实为分支提示提供了另一种选择。
    【解决方案2】:

    您可能想查看this question 的答案。 如果您有任何在 Windows 上运行的想法,您可能想要 look at this 也是。

    几乎肯定值得您花时间查看分支预测的解释this question 的答案中。 (请注意,在该问题中观察到的行为不仅跨编译器而且跨语言都很常见,Java 和 C++ 中的示例说明了这一点。)

    据我了解,问题与

    if (val == 0.0)
    {
      // extremely unlikely code path
    }
    

    是分支预测器最初会假设条件为真, 也就是说,它将开始执行你极不可能的 第一次遇到这种情况的代码路径。 分店的成本与其说是评价val == 0.0 但是当val == 0.0 被证明是错误的时,退出不太可能的分支的成本。 然而,在它遇到了几次分支语句之后, 分支预测器会猜测条件为假,然后执行 就像你告诉编译器“假”分支是 最有可能的。

    在这样的环境下运行,一般不需要优化分支, 因为它将为您优化。 您可以对分支进行的唯一优化是优化第一次 当它被调用时(可能还有其他几次,具体取决于 分支预测算法寻找)。 如果您的应用程序对性能至关重要,以至于您负担不起这笔费用 即使是第一次或两次运行函数,你应该用 C++ 编程吗?

    为了鼓励分支预测器第一次走正确的路径, 但是,你可以写

    if (val != 0.0)
    {
      // stuff you want to do almost every time
    }
    else
    {
      // extremely unlikely code path
    }
    

    这有两个优点:首先,它是便携的, 其次,它得到了极不可能的代码 不碍事,这样您就可以更容易地看到代码通常应该做什么。 缺点是它增加了另一个级别的缩进 // stuff you want to do almost every time.

    我承认自己使用过这种技术。

    【讨论】:

      【解决方案3】:

      您需要知道在其中设置该条件是否会严重损害性能。 This is the method I use.

      我倾向于假设,如果对时间要求严格的代码存在性能问题,那么应该追查该问题的实际情况。 在诊断证明之前不要假设条件性伤害。

      【讨论】:

        猜你喜欢
        • 2016-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-16
        • 1970-01-01
        相关资源
        最近更新 更多