如果x> y,将x与y交换的无分支版本?

时间:2019-03-09 12:17:27

标签: c++ c++11 optimization

假设xy是有符号整数,是否有一些超高效的实现技巧:

if (x < y) {
    std::swap(x, y);
}

我可以立即想到使用c = x < y的解决方案,然后将x分配给c * x + (1 - c) * y等。但是这种方法会发出乘法指令,我想避免这种情况。有没有办法单独摆弄呢?

编辑:只是澄清一下,我真正关心的是试图摆脱由if引起的分支。换句话说,我知道进行交换的XOR技巧,但这不是我要的。

3 个答案:

答案 0 :(得分:4)

我不确定,这是否是您的代码,但这是无分支解决方案:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
  int a = atoi(argv[1]);
  int b = atoi(argv[2]);
  int c = a - b;
  c &= c >> 31; // SXT for signed int
  a -= c;
  b += c;
  printf("Result: %d %d\n", a, b);
}

答案 1 :(得分:2)

如果在此操作之后将xy写入了内存,则可以使用对动态内存位置的写操作来代替条件跳转。例如,对a[0], a[1]进行排序:

int x = a[0];
int y = a[1];
a[x >= y] = x;
a[y > x] = y;

如果您需要立即读回这些值,那么它甚至可能比可预测的分支要慢,但它可能取决于处理器。

答案 2 :(得分:0)

根据其他人的建议,您可以尝试根据std::min()std::max()重写代码。

但是不能保证。该语言只是缺乏一种表达您想要的编译器内容的方法。

关于我可能提供的唯一其他非C ++解决方案将是内联汇编,您可以在其中精确地编写所需的指令。但是,使用内联汇编会影响编译器对其周围代码的处理,并且可能会产生负面影响(例如,寄存器使用效率低下,寄存器溢出等),从而抵消或抵消任何预期的收益。