我需要优化表单的表达式:
(a > b) || (a > c)
我尝试了几种优化形式,其中一种如下:
(a * 2) > (b + c)
优化不是来自编译器的观点。我想将两个> s减少到一个。
这是基于1< =(a,b,c)< = 26
的假设但是,这仅适用于某些情况。我正在努力做的优化,真的可能吗?如果是的话,开始会非常有帮助。
答案 0 :(得分:4)
答案可能是:你不想优化它。而且,我怀疑有没有办法更有效地写这个。如果你说a,b和c是1到26之间的值,你不应该使用整数(你不需要那个精度),如果你想要最佳(大小)。
如果是> b,表达式a> c无论如何都不会被执行。因此,您最多有2个(并且至少1个)条件运算,这实际上不值得进行优化。
答案 1 :(得分:2)
我很怀疑这在大多数情况下甚至是优化。
a > b || a > c
将评估为:
compare a b
jump not greater
compare a c
jump not greater
其中
a * 2 > b + c
给出:
shift a left 1 (in temp1)
add b to c (in temp2)
compare temp1 temp2
jump if not greater
与性能一样,基于实际性能测量(最好是选择处理器架构)的决策总是好得多。
答案 2 :(得分:1)
我能想到的最好的就是这个
char a, b, c;
std::cin >> a >> b >> c;
if (((b-a) | (c-a)) & 0x80) {
// a > b || a > c
}
使用gcc -O2
,这只生成一个条件分支
40072e: 29 c8 sub %ecx,%eax
400730: 29 ca sub %ecx,%edx
400732: 09 d0 or %edx,%eax
400734: a8 80 test $0x80,%al
400736: 74 17 je 40074f <main+0x3f>
这会利用输入值的约束,因为值不能大于26,然后从a
减去b
会在a > b
时给你一个负值,在两个补码中知道位7
将在这种情况下设置 - 同样适用于c
。然后我 OR 两者,以便位7
指示a > b || a > c
,最后我们通过 AND 检查位7
和0x80并且分支这一点。
更新:出于好奇,我计划了4种不同的编码方式。为了生成测试数据,我使用了一个简单的线性同余伪随机数发生器。我将它定时循环1亿次迭代。为简单起见,我假设如果条件为真,我们想将5添加到计数器,否则不执行任何操作。我使用g++ (GCC) 4.6.3 20120306 (Red Hat 4.6.3-2)
使用Intel Xeon X5570 @ 2.93GHz
使用-O2
优化级别时使用#include <iostream>
unsigned myrand() {
static unsigned x = 1;
return (x = x * 1664525 + 1013904223);
}
int main() {
size_t count = 0;
for(size_t i=0; i<100000000; ++i ) {
int a = 1 + myrand() % 26;
int b = 1 + myrand() % 26;
int c = 1 + myrand() % 26;
count += 5 & (((b-a) | (c-a)) >> 31); // 0.635 sec
//if (((b-a) | (c-a)) & 0x80) count += 5; // 0.660 sec
//if (a > std::max(b,c)) count += 5; // 0.677 sec
//if ( a > b || a > c) count += 5; // 1.164 sec
}
std::cout << count << std::endl;
return 0;
}
进行计时。
这是代码(注释掉除了一个条件变体之外的所有变量):
1s
最快的是对我的答案中的建议进行了修改,我们使用符号扩展来生成32 0s
或32 5
的掩码,具体取决于条件是否为false,并使用它来屏蔽正在添加的( a > b || a > c)
,以便它添加5或0.此变体没有分支。时间在每一行的评论中。最慢的是原始表达式{{1}}。