找出最大值;最小的两个号码没有使用否则?

时间:2014-07-02 11:04:37

标签: c optimization bit-manipulation bit bitwise-operators

我能够从Here

中找到逻辑
r = y ^ ((x ^ y) & -(x < y)); // min(x, y)
r = x ^ ((x ^ y) & -(x < y)); // max(x, y)

它说它比做

更快
r = (x < y) ? x : y

有人可以通过示例来解释它以了解它。 怎么可能更快?

5 个答案:

答案 0 :(得分:10)

在没有特定硬件的情况下讨论优化并没有任何意义。在没有详细介绍特定系统的情况下,您真的无法告诉哪个替代方案最快。在没有任何特定硬件的情况下,大胆地发表关于第一个替代品最快的声明,只是预先成熟的优化。

如果给定CPU的性能严重依赖于branch prediction,那么模糊的xor解决方案可能比比较替代方案更快。换句话说,如果它执行常规指令(例如算术指令)非常快,但在任何条件语句(例如if)处获得性能瓶颈,其中代码可能以多种方式分支。诸如量指令高速缓冲存储器等的其他因素也很重要。

然而,许多CPU将更快地执行第二种替代方案,因为它涉及更少的操作。

总而言之,您必须成为给定CPU的专家,才能在理论上实际告诉哪些代码最快。如果您不是这样的专家,只需对其进行基准测试即可。或者看一下反汇编的显着差异。

答案 1 :(得分:5)

在您提供的链接中,明确声明:

  

在一些罕见的机器上,分支非常昂贵并且没有条件移动指令,[code]可能比明显的方法更快,r =(x

后来,它说:

  

在某些机器上,将(x

简而言之,位操作解决方案仅在分支执行较差的机器上更快,因为它仅依赖于操作数的数值。在大多数机器上,分支方法同样快(有时甚至更快),因其可读性而应该是首选。

答案 2 :(得分:0)

使用条件分支(而不是条件分配)实现?风险。

有条件的分支是一个小小的灾难&#34;对于处理器,因为它无法猜测以后将获取什么指令。这打破了ALU的管道组织(正在同时进行若干指令以增加吞吐量),并导致管道重新初始化延迟。为了缓解这一点,处理器采用分支预测,即他们在将要采取的分支上下注,但他们不能一直成功。

总之:条件分支可以是slloooowwwwwwww ...

答案 3 :(得分:0)

该问题未指定将运行的硬件。我的答案将解决在x86上运行的情况(例如任何PC)。让我们看看每个生成的程序集。

; r = y ^ ((x ^ y) & -(x < y))
xor    edx,edx
cmp    ebx,eax
mov    ecx,eax
setl   dl
xor    ecx,ebx
neg    edx
and    edx,ecx  
xor    eax,edx  

; r = (x < y) ? x : y
cmp    ebx,eax  
cmovl  eax,ebx  

XOR版本必须将寄存器归零并在其本身需要执行的操作之上移动值,最多可添加8条指令。但是x86有一个cmov或条件移动指令。因此?:版本编译为比较和cmovl,仅编译2条指令。但是,由于不同的指令可能具有不同的延迟和不同的依赖链,因此这不需要使?:版本快4倍。但你可以肯定地看到?:很可能比XOR版本更快。

同样值得注意的是,这两个版本都不需要分支,因此没有分支错误预测惩罚。

答案 4 :(得分:0)

使用位操作:

void func(int a,int b){
    int c = a - b;
    int k = (c >> 31) & 0x1;
    int max = a - k * c;
    int min = b + k * c;
    printf("max = %d\nmin = %d",max,min);
    }