2012-10-05 7 views
9

Queste sono 2 funzioni, fun1 accetta 1 parametro, fun2 richiede 4 parametri aggiuntivi inutili. Quando ho scelto come target x64, lo fun1 richiede 4 secondi ma lo fun2 richiede meno di 1 secondo. Se ho preso di mira anycpu, entrambi richiedono meno di 1 secondo.Il targeting per x64 a volte può comportare prestazioni pessime rispetto a anycpu

C'è una domanda simile ho chiesto qui why Seq.iter is 2x faster than for loop if target is for x64?

E 'compilato in .Net 4.5 Visual Studio 2012, F # 3.0, eseguito in Windows 7 x64

open System 
open System.Diagnostics 

type Position = 
    { 
     a: int 
     b: int 
    } 

[<EntryPoint>] 
let main argv = 

    let fun1 (pos: Position[]) = //<<<<<<<< here 
     let functionB x y z = 4 

     Array.fold2 (fun acc x y -> acc + int64 (functionB x x y)) 0L pos pos 

    let fun2 (pos: Position[]) u v w x = //<<<<<<<< here 
     let functionB x y z = 4 

     Array.fold2 (fun acc x y -> acc + int64 (functionB x x y)) 0L pos pos 



    let s = {a=2;b=3} 
    let pool = [|s;s;s|] 

    let test1 n = 
     let mutable x = 0L 
     for i in 1 .. n do 
      x <- fun1 pool 

    let test2 n = 
     let mutable x = 0L 
     for i in 1 .. n do 
      x <- fun2 pool 1 2 3 4 

    let sw = new Stopwatch() 
    sw.Start() 
    test2 10000000 
    sw.Stop() 
    Console.WriteLine(sw.Elapsed) 

    sw.Restart() 
    test1 10000000 
    sw.Stop() 
    Console.WriteLine(sw.Elapsed) 


    0 // return an integer exit code 
+3

Posso riprodurre con VS2012 RTM: il primo codice richiede ~ 4 secondi, il secondo è <1 secondo. Inoltre, ci vuole un extra di quattro parametri perché ci sia qualche differenza; l'aggiunta di tre extra richiede ancora ~ 4 secondi. – ildjarn

+1

Curiosamente non c'è una ragione ovvia per l'accelerazione - ho confrontato lo smontaggio ed è identico tranne nel secondo caso sono state aggiunte più istruzioni per caricare i parametri extra che avrei dovuto rallentare. –

+0

Strano. Sono praticamente uguali per me (~ 4) ... in realtà il secondo richiede costantemente un pelo più lungo. (VS2012 RTM .NET 4.5) – Daniel

risposta

0

La differenza è quasi certamente un cavillo del JITer. Spiega anche i risultati incoerenti. Questo è un problema comune con test di micro-benchmark come questo. Esegui una o più esecuzioni ridondanti dei metodi per compilare il tutto dietro le quinte e cronometrare l'ultimo. Saranno identici.

È possibile ottenere risultati più bizzarri di questo a causa di questa stranezza.

2

Questa non è una risposta completa, è la prima diagnostica del problema.

Posso riprodurre il comportamento con la stessa configurazione. Se attivi F # Interactive a 64 bit in Tools -> Options -> F# Tools -> F# Interactive, puoi osservare lo stesso comportamento lì.

Differenza da the other question, j64 jitter non è un problema. Risulta che l'opzione "Genera chiamate coda" nella proprietà Project causa un notevole rallentamento di test1 rispetto a test2. Se si disattiva questa opzione, due casi hanno velocità simili.

D'altra parte, è possibile utilizzare la parola chiave inline su fun1 in modo che la chiamata coda non sia necessaria. Due esempi sono comparabili nel tempo di esecuzione, non importa fun2 è in linea o meno.

Detto questo, è strano che l'aggiunta dell'opcode tail. a fun1 lo renda molto più lento di (facendo lo stesso con) fun2. È possibile contattare il team F # per ulteriori indagini.

Problemi correlati