2013-04-16 29 views
13

以下代碼導致slow1 = 1323 msslow2 = 1311 msfast = 897 ms。這怎麼可能?「嵌套if」與「if and」性能使用F#

這裏:Nested or not nested if-blocks?他們提到

任何現代編譯器,和我的意思是建立在過去20年中任何東西,將編譯這些相同的代碼。

let s = System.Diagnostics.Stopwatch() 
let mutable a = 1 
s.Start() 

for i in 0 .. 1000000000 do 
    if i < 0 then 
    if i < 0 then 
     a <- 4 

printfn "fast = %d" s.ElapsedMilliseconds 

s.Restart() 

for i in 0 .. 1000000000 do 
    if i < 0 && i < 0 then 
    a <- 4 

printfn "slow1 = %d" s.ElapsedMilliseconds 

s.Restart() 

for i in 0 .. 1000000000 do 
    if i < 0 & i < 0 then 
    a <- 4 

printfn "slow2 = %d" s.ElapsedMilliseconds 
+0

您是否在發佈模式下嘗試過? –

+1

是的。此外任何CPU,X86和X64。在調試模式下,兩個版本都變得相當慢(3083毫秒)。 –

+0

我必須說,同樣緩慢的結果使得更多的「意義」,然後不同的... –

回答

4

我已經接到了反彙編,我將在這裏發表有人來闡述(沒時間)的MSIL的保留 - 這是社區維基時間:

快速(只是i比較線作爲其餘是相同的):

//000030: if i < 1000 then 
    IL_001f: ldloc.0 
    IL_0020: ldc.i4  0x3e8 
    IL_0025: bge.s  IL_003b 
//000031:  if i < 1000 then 
    IL_0027: ldloc.0 
    IL_0028: ldc.i4  0x3e8 
    IL_002d: bge.s  IL_0038 

慢速:

//000039: if i < 1000 && i < 1000 then 
    IL_0084: ldloc.0 
    IL_0085: ldc.i4  0x3e8 
    IL_008a: bge.s  IL_0097 
    IL_008c: ldloc.0 
    IL_008d: ldc.i4  0x3e8 
    IL_0092: clt 
    IL_0094: nop 
    IL_0095: br.s  IL_0099 
    IL_0097: ldc.i4.0 
    IL_0098: nop 
    IL_0099: brfalse.s IL_00a4 

在附註中,兩個版本的C#版本具有相同的時序。

我在反彙編中注意到的一件事是F#變量是Program.i和Program.a,所以我不確定F#中是否存在一些C#中沒有的對象干擾。距離Don賽姆

+0

'nop'不應該在那裏在一個優化的版本。 – usr

+0

@usr我不知道你是對的... –

+0

這是一個輸出發佈版本打開優化(VS2012)沒有關於優化的詳細信息,只是打開或關閉 –

4

電子郵件:

是的,我們已經注意到線程和記錄的問題。這不完全是一個錯誤(代碼正確執行),但在這裏獲得等效的perf肯定會很好。

+1

你可以告訴唐,既然F#developer \發燒友社區還很小,而且F#開發團隊似乎是一堆(在編譯器開發人員標準中),我們很想得到一些個人關注:-) –