learn f# compilation

f# learn



Pregunta de rendimiento F#: ¿qué está haciendo el compilador? (1)

Haciendo referencia a este código: F # Restricciones del tipo de miembro estático

¿Por qué es, por ejemplo,

let gL = G_of 1L [1L..100000L] |> List.map (fun n -> factorize gL n)

significativamente más lento que

[1L..100000L] |> List.map (fun n -> factorize (G_of 1L) n)

Al observar Reflector, puedo ver que el compilador está tratando cada uno de estos de maneras muy diferentes, pero hay mucho que hacer para descifrar la diferencia esencial. Ingenuamente, asumí que el primero funcionaría mejor que el anterior porque gL está precalculado mientras que G_of 1L tiene que calcularse 100.000 veces (al menos así parece).

[ Editar ]

Parece que esto puede ser un error con F # 2.0 / .NET 2.0 / Release-mode, vea la respuesta y discusión de @protbot.


Reflector muestra test2 () convertido en 4 clases mientras test1 () se convierte en dos clases. Esto solo ocurre en el modo de depuración. El reflector muestra un código idéntico (una clase para cada uno) en el modo de lanzamiento. Lamentablemente, Reflector se cuelga cuando intento ver la fuente en C # y el IL es realmente largo.

let test1() = let gL = G_of 1L [1L..1000000L] |> List.map (fun n -> factorize gL n) let test2() = [1L..1000000L] |> List.map (fun n -> factorize (G_of 1L) n)

Un punto de referencia rápido.

let sw = Stopwatch.StartNew() test1() |> ignore sw.Stop() Console.WriteLine("test1 {0}ms", sw.ElapsedMilliseconds) let sw2 = Stopwatch.StartNew() test2() |> ignore sw2.Stop() Console.WriteLine("test2 {0}ms", sw2.ElapsedMilliseconds)

Los puntos de referencia funcionaron en I7 950 @ 3368Mhz, Windows 7 64bit, VS2010 F # 2.0

Depuración x86
test1 8216ms
test2 8237ms

Versión x86
test1 6654ms
test2 6680ms

Depuración x64
test1 10304ms
test2 10348ms

Versión x64
test1 8858ms
test2 8977ms

Aquí está el código completo.

open System open System.Diagnostics let inline zero_of (target:''a) : ''a = LanguagePrimitives.GenericZero<''a> let inline one_of (target:''a) : ''a = LanguagePrimitives.GenericOne<''a> let inline two_of (target:''a) : ''a = one_of(target) + one_of(target) let inline three_of (target:''a) : ''a = two_of(target) + one_of(target) let inline negone_of (target:''a) : ''a = zero_of(target) - one_of(target) let inline any_of (target:''a) (x:int) : ''a = let one:''a = one_of target let zero:''a = zero_of target let xu = if x > 0 then 1 else -1 let gu:''a = if x > 0 then one else zero-one let rec get i g = if i = x then g else get (i+xu) (g+gu) get 0 zero type G<''a> = { negone:''a zero:''a one:''a two:''a three:''a any: int -> ''a } let inline G_of (target:''a) : (G<''a>) = { zero = zero_of target one = one_of target two = two_of target three = three_of target negone = negone_of target any = any_of target } let inline factorizeG n = let g = G_of n let rec factorize n j flist = if n = g.one then flist elif n % j = g.zero then factorize (n/j) j (j::flist) else factorize n (j + g.one) (flist) factorize n g.two [] let inline factorize (g:G<''a>) n = //'' let rec factorize n j flist = if n = g.one then flist elif n % j = g.zero then factorize (n/j) j (j::flist) else factorize n (j + g.one) (flist) factorize n g.two [] let test1() = let gL = G_of 1L [1L..100000L] |> List.map (fun n -> factorize gL n) let test2() = [1L..100000L] |> List.map (fun n -> factorize (G_of 1L) n) let sw2 = Stopwatch.StartNew() test1() |> ignore sw2.Stop() Console.WriteLine("test1 {0}ms", sw2.ElapsedMilliseconds) let sw = Stopwatch.StartNew() test2() |> ignore sw.Stop() Console.WriteLine("test2 {0}ms", sw.ElapsedMilliseconds) Console.ReadLine() |> ignore