c++ - 编译器是否能够避免分支指令?

标签 c++ c++11 bit-manipulation c++14 micro-optimization

我一直在阅读 bit twiddling hacks并思考,编译器是否能够避免以下代码中的分支:

constexpr int min(const int lhs, const int rhs) noexcept {
    if (lhs < rhs) {
        return lhs;
    }
    return rhs
}

将其替换为 ( explanation ):

constexpr int min(const int lhs, const int rhs) noexcept {
    return rhs ^ ((lhs ^ rhs) & -(lhs < rhs));
}

最佳答案

  • Are compilers able to...:肯定是的!
  • 我可以依赖那些优化吗?:不,你不能依赖任何优化。可能总会有一些奇怪的情况,在这种情况下,编译器会出于某些不明显的原因选择不实现某种优化,或者只是看不到这种可能性。另外,总的来说,我观察到编译器有时比人们想象的要笨得多(或者人们(包括我)比他们想象的要笨)。(1)
  • 没有问,但有一个非常重要的方面:我可以相信这实际上是一种优化吗?不!一方面,(尤其是在 x86 上)性能总是取决于周围的代码,并且有很多不同的优化相互作用。此外,一些架构甚至可能提供更高效地执行操作的命令。
  • 我应该使用位旋转优化吗?:一般来说:不 - 尤其是在没有验证它们确实给您带来任何好处的情况下!即使它们确实提高了性能,它也会使您的代码更难阅读和审查,并且它会做出一些特定于体系结构和编译器的假设(整数的表示、指令的执行时间、分支预测错误的惩罚……),这可能会导致当您将代码移植到另一个体系结构时性能会更差,或者在最坏的情况下甚至会导致错误的结果。

我的建议:
如果您需要获得特定系统 的最后一点性能,那么只需尝试两种变体并进行测量(并在每次更新您的 CPU 和/或编译器时验证结果)。对于任何其他情况,假设编译器至少在进行低级优化方面与您一样好。我还建议您首先了解所有与优化相关的编译器标志,并在任何情况下开始使用低级优化之前设置适当的基准。

我认为手动优化有时仍然有益的唯一领域是,如果您想最佳地使用 vector 单元。现代编译器可以自动矢量化很多东西,但这仍然是一个相对较新的领域,并且编译器不允许做某些事情,因为它违反了标准的某些保证(尤其是在涉及浮点运算的情况下)。

(1) 有些人似乎认为,不管他们的代码是什么样子,编译器总是会产生提供相同语义的最佳代码。首先,编译器在有限的时间内可以做什么是有限制的(有很多启发式方法在大多数情况下都有效,但并非总是如此)。其次,在很多情况下,c++ 标准要求编译器提供某些保证,您目前实际上并不感兴趣,但仍然会阻止优化。

关于c++ - 编译器是否能够避免分支指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32295315/

相关文章:

c++ - 从函数返回 vector 以打印内容

c++ - 调用函数作为默认参数可以吗?

c++ - STL 在 C++ 中的强大功能

c - 意外的 C/C++ 移位运算符结果

java - 隐写术后第一个字节的位相差一位

c - 关于交换位的问题

c++ - C++的并发集?

c++ - 模板别名范围

c++ - C++ 中重载的 lambda 以及 clang 和 gcc 之间的区别

c++ - 如何专门化依赖于类的静态数据成员的模板?