2012-10-05 7 views
9

Są to 2 funkcje, fun1 przyjmuje 1 parametr, fun2 pobiera 4 dodatkowe niepotrzebne parametry. Kiedy celowałem na x64, fun1 trwa 4s, ale fun2 zajmuje mniej niż 1s. Jeśli celowałem w anycpu, oba biorą mniej niż 1s.Ukierunkowane na procesory x64 może czasami powodować bardzo niską wydajność niż w przypadku anycpu

Jest podobne pytanie poprosiłem o why Seq.iter is 2x faster than for loop if target is for x64?

jest skompilowany w .NET 4.5 Visual Studio 2012, C# 3.0, należy uruchomić w systemie 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

Mogę repro z VS2012 RTM - twój pierwszy kod trwa ~ 4 sekundy, twoja sekunda to <1 sekunda. Ponadto, aby uzyskać jakąkolwiek różnicę, potrzeba dodatkowych czterech dodatkowych parametrów; dodanie trzech dodatkowych zdjęć trwa ~ 4 sekundy. – ildjarn

+1

Intrygujące, że nie ma żadnego oczywistego powodu dla przyspieszenia - porównałem demontaż i jest on identyczny, z wyjątkiem drugiego przypadku dodano więcej instrukcji, aby załadować dodatkowe parametry, których oczekiwałbym, że spowolnią to. –

+0

Dziwne. Są praktycznie dla mnie takie same (~ 4) ... w rzeczywistości druga z nich konsekwentnie zajmuje dłużej włosy. (VS2012 RTM .NET 4.5) – Daniel

Odpowiedz

0

Różnica jest prawie na pewno dziwactwo JITera. Wyjaśnia także niespójne wyniki. Jest to powszechny problem w testach mikro-benchmarkingowych, takich jak ten. Wykonaj jedną lub więcej nadmiarowych wykonań metod, aby skompilować całość za kulisami, a czas ostatni. Będą identyczne.

Dzięki temu dziwactwu można uzyskać bardziej dziwne wyniki.

2

To nie jest kompletna odpowiedź, to pierwsza diagnostyka problemu.

Mogę odtworzyć zachowanie w tej samej konfiguracji. Jeśli włączysz F # Interactive 64-bit w Tools -> Options -> F# Tools -> F# Interactive, możesz zaobserwować to samo zachowanie.

Odmienna od the other question, jitter x64 nie stanowi problemu. Okazuje się, że "Generuj wywołania ogniskowe" Opcja we właściwości Projekt powoduje znaczne spowolnienie w postaci test1 w porównaniu z test2. Jeśli wyłączysz tę opcję, dwa przypadki mają podobną prędkość.

Z drugiej strony można użyć słowa kluczowego inline na fun1, aby wywołanie ogona nie było potrzebne. Dwa przykłady są porównywalne w czasie wykonywania ponownie, niezależnie od tego, czy fun2 jest zaznaczone czy nie.

To powiedziawszy, to jest dziwne, że dodanie kodu opozycyjnego tail. do fun1 powoduje, że jest on znacznie wolniejszy niż (robiąc to samo z) fun2. Możesz skontaktować się z zespołem F # w celu dalszego dochodzenia.

Powiązane problemy