【发布时间】:2019-03-11 16:29:52
【问题描述】:
假设x 和y 是有符号整数,是否有一些超级有效的实现技巧:
if (x < y) {
std::swap(x, y);
}
我可以立即想到使用c = x < y 的解决方案,然后将x 分配给c * x + (1 - c) * y 等,但这种方法会发出乘法指令,我想避免这种方法。有没有办法只用一点点摆弄来做到这一点?
编辑:只是澄清我真正关心的是试图摆脱由if 引起的分支。换句话说,我知道进行交换的 XOR 技巧,但这不是我要问的。
【问题讨论】:
-
编译器很聪明——你为什么要担心这个?
-
我想是否有可能摆脱分支取决于 CPU(例如,上述 gobolt 链接基于类似 Intel 的东西)
-
分支并不总是很慢,只要比较是可预测的(并且 CPU 真的很擅长)。您的代码就像
X = x; Y = y; x = std::max(X, Y); y = std::min(X, Y);一样,无需分支即可轻松完成,但需要 2 个cmovcc,这可能比分支慢。根据我的经验,ICC 使用cmovcc比 Clang 更多,而 Clang 又比 gcc 更频繁地发出这些指令。 Sample -
几乎所有上述替代方案都只是用代码中不太明显的分支替换了一个容易看到的分支。
c = x < y或?:或std::max都包含一个基本解析为分支(或 2)的条件。在大多数示例中,替代代码更复杂并且可能更慢。 如果有优化,编译器可能还是会打结。除非分析显示卷轴性能问题,否则请避免使代码更难理解的微优化。如果你仍然编写这样的代码,请确保性能增益足够大以证明它是合理的。 -
您是否使用
cmp/mov/cmovele/cmovl(the code clang emits) 将此代码与内联汇编进行了基准测试? Sometimes branching is faster than a conditional move (here's another reference)。如果您可以将cmp从cmov展开,它也可能会有所帮助。
标签: c++ c++11 optimization