我正在阅读其他网站(Computer Science - Can a Minimum Possible Efficiency be proven?)关于为最坏情况假设最小Big-O时间的文章。
其中一个答案用于解释比较二进制值(或类似值)所需时间的长度。
我对自己说:为什么不按位操作?
我在Javascript中制作了这个模拟代码:
console.time('^');
for(var i=0;i<1e5;i++)13^15;
console.timeEnd('^');
console.time('!=');
for(var i=0;i<1e5;i++)13!=15;
console.timeEnd('!=');
我真的很惊讶!
使用^
(bitwise-xor)的循环几乎可以 3ms !
这怎么可能?
为什么bitwise-xor(^
)比不等于(!=
)comparisson快?
其他可能相关的信息:
我已经在Windows 7 Home Premium x64上运行的Firefox 34.0.5上进行了测试。
我还在Opera 12.17(x64)和Chrome 39.0.2171.95上尝试了这个代码,行为几乎相似,使用^
的代码更快80%的测试。
另一个惊喜:
在php中,运行这个:
$now=microtime(true);
for($i=0,$x=0;$i<1e6;$i++)$x+=13^15;
echo microtime(true)-$now,PHP_EOL;
$now=microtime(true);
for($i=0,$x=0;$i<1e6;$i++)$x+=13!=15;
echo microtime(true)-$now,PHP_EOL;
显示完全效果相同:^
比!=
快。
使用$x+=!13^15;
代替$x+=13^15;
的时间更快70%。
我已在http://writecodeonline.com/php/上测试,它在linux x64上运行PHP 5.3。
此代码向用户@AlexK。提出以下评论的建议:
13 ^ 15是一个常数noop,也许它只是简单地优化了(尝试有效的x + = 13 ^ 15;)
答案 0 :(得分:1)
你正在咆哮着错误的树木。
比如说,一个2GHz的CPU,^或!=可以在纳秒或其附近执行。执行1e6将需要1ms,而不是460ms。这告诉我两件事:
for
需要花费大量时间,请注意,口译员不一定要花时间优化。一个非常好的优化器会将for($i=0,$x=0;$i<1e6;$i++)$x+=13^15;
变为$x = 2000000
。它显然没有那样做。好的,很难判断它是否已$x+=13^15
变为$x+=2
。
让我们看看另一件事。在机器级别,甚至在间隔级别$x+=13!=15
都比$x+=13^15
更复杂。两者都涉及$x+=
,但13^15
是单个操作,而13!=15
(在此上下文中!)是两个操作 - 首先比较!=
的13和15以获得真,然后将true转换为1.硬件级别有很多方法可以做到 - 大多数都涉及跳转,这是很昂贵的。还有其他技术涉及多个布尔/移位/等指令,只是为了避免跳转。
也许13!=15
速度较慢。但由于for循环的显着开销,你不知道多少。
无论如何,这有关系吗?是否存在这两种操作可以互换的情况?您没有与可能相同的(13^15)!=0
进行比较。