我能够从Here
中找到逻辑r = y ^ ((x ^ y) & -(x < y)); // min(x, y)
r = x ^ ((x ^ y) & -(x < y)); // max(x, y)
它说它比做
更快r = (x < y) ? x : y
有人可以通过示例来解释它以了解它。 怎么可能更快?
答案 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);
}