基于布尔切换的高效对称比较

时间:2019-07-05 14:53:47

标签: c++ c

我的代码有很多类似的模式

int a, b.....
bool c = x ? a >= b : a <= b;

,对于其他不平等比较运算符也类似。有没有一种方法可以编写此代码以实现x86的更好性能/无分支。

请为我提供have you benchmarked your code? Is this really your bottleneck?类型的注释。我要求其他方式编写此代码,以便可以进行基准测试。

编辑:

bool x

5 个答案:

答案 0 :(得分:2)

原始表达:

x ? a >= b : a <= b

无分支等效表达式,无短路评估:

!!x & a >= b | !x & a <= b

这是不使用算术欺骗手段的通用模式的示例。注意操作员的优先级;对于更复杂的示例,您可能需要括号。

答案 1 :(得分:2)

另一种方式是:

bool c = (2*x - 1) * (a - b) >= 0;

这会在此处生成无分支的代码:https://godbolt.org/z/1nAp7G

#include <stdbool.h>
bool foo(int a, int b, bool x)
{
    return (2*x - 1) * (a - b) >= 0;
}
------------------------------------------
foo:
        movzx   edx, dl
        sub     edi, esi
        lea     eax, [rdx-1+rdx]
        imul    eax, edi
        not     eax
        shr     eax, 31
        ret

答案 2 :(得分:1)

您当前拥有的方式可能是无与伦比的。

但是对于正整数abbool x,您可以使用

a / b * x + b / a * !x

(您可以使用a替换a + 1,并在需要支持零的情况下类似地替换b,以适应额外的CPU消耗。)

答案 3 :(得分:1)

由于您只是在寻找等效的表达式,所以这来自修补@AlexanderZhang的注释:

(a==b) || (c != (a<b))

答案 4 :(得分:-1)

如果a> = b,则a-b将为正,并且第一位(符号位)为0。否则a-b为负,并且第一位为1。 因此,我们可以简单地“异或” a-b的第一位和x的值

constexpr auto shiftBit = sizeof(int)*8-1;
bool foo(bool x, int a, int b){
    return  x ^ bool((a-b)>>shiftBit);
}

foo(bool, int, int):
        sub     esi, edx
        mov     eax, edi
        shr     esi, 31
        xor     eax, esi
        ret