2015-01-13 53 views
3

我正在閱讀其他網站(Computer Science - Can a Minimum Possible Efficiency be proven?)的文章,關於在最壞的情況下假設最小的大O時間。爲什麼在Firefox中爲bitwise-xor(^)比不等於(!=)comparisson更快?

其中一個答案的長度解釋了比較二進制值(或類似)所需的時間。

而我雖然對自己:爲什麼不按位操作?

而且我在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?


其他可能相關的信息:

我已經在Firefox 34.0.5測試了Windows 7家庭高級版64位運行。

我也在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是一個恆定空操作,也許是其簡單地優化掉(試一下有效X + = 13^15; )

+2

將迭代計數增加10倍以排除噪聲影響並給出百分比差異。沒有參考比較它的絕對值是沒有意義的。 – usr

+0

@usr你有沒有任何例子可以讓我瞭解如何做到這一點,而不會使用printscreens淹沒這篇文章? –

+0

只是說「它快了x%」。我被迫自己運行這個基準來發現。 – usr

回答

1

你在吠叫錯誤的樹木。

例如,在2GHz的CPU上,^或!=可以在納秒左右執行。執行1e6將需要1ms,而不是460ms。這告訴我兩件事情:

  1. for花費的時間顯著量,
  2. JavaScript是解釋編譯

請注意,口譯員不一定花時間優化。一個非常好的優化器會將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,這可能是等效的。

+0

也許我真的從錯誤的角度看待這個問題。這個想法是爲了避免使用'!='來加速排序算法。但速度差異是真實的。在'for'中,在這種情況下,嘗試用'i^1e5'和'i!= 1e5'分別替換'i <1e5'。在谷歌瀏覽器上,它在82-88ms和'for(var i = 0; i!= 1e5; i ++)運行'for(var i = 0; i^1e5; i ++)13! '在98-99ms。如果需要,我可能會提供打印屏幕。對於($ i = 0,$ x = 0; $ i <1e6; $ i ++)$ x + = 13^15;'這行是PHP的(但它也可以在Javascript上運行)。但即使在PHP上,趨勢也是一樣的。 (繼續) –

+0

引用你的回答:'「無論如何,這有什麼關係?這兩種操作是否可以互換?「 - >是的,你可以用它來檢查兩個數字是否不同,'1^1e5'應該產生一個與'1!= 1e5相同的真值''1e5^1e5'應該產生與'1e5!= 1e5'相同的真實結果,它們不是一直可以互換的,但是對於這個特殊情況,我想它很重要,對吧? –

+0

測試case需要從boolean(true/false)轉換爲一個數字,以便可以執行'+ =',如果代之以保持true/false,代碼可能會更快。 –

相關問題