2012-10-05 13 views
9

Estas son 2 funciones, fun1 toma 1 parámetro, fun2 toma 4 parámetros extra inútiles. Cuando seleccioné x64, fun1 toma 4s pero fun2 lleva menos de 1s. Si apunté a anycpu, ambos tomaron menos de 1s.Dirigido a x64 algunas veces resultaría en un rendimiento muy malo que para anycpu

Hay una pregunta similar le pregunté aquí why Seq.iter is 2x faster than for loop if target is for x64?

Se compila en .Net 4.5 de Visual Studio 2012, C# 3.0, ejecute en 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

Puedo reproducir con VS2012 RTM - su primer código tarda ~ 4 segundos, su segundo es <1 segundo. Además, toma un total de cuatro parámetros adicionales para que haya alguna diferencia; agregar tres extra todavía lleva ~ 4 segundos. – ildjarn

+1

Curiosamente, no hay una razón obvia para la aceleración: comparé el desmontaje y es idéntico, excepto en el segundo caso en el que se agregan más instrucciones para cargar los parámetros adicionales, lo que habría esperado que fuera más lento. –

+0

Extraño. Son prácticamente lo mismo para mí (~ 4) ... en realidad, el segundo siempre lleva más pelo. (VS2012 RTM .NET 4.5) – Daniel

Respuesta

0

La diferencia es casi seguro que una peculiaridad del JITer. También explica los resultados inconsistentes. Este es un problema común con las pruebas de micro-benchmarking como esta. Realice una o más ejecuciones redundantes de los métodos para compilar todo detrás de las escenas y cronometrar la última. Ellos serán idénticos.

Puede obtener resultados más extraños debido a esta peculiaridad.

2

Esto no es una respuesta completa, es el primer diagnóstico del problema.

Puedo reproducir el comportamiento con la misma configuración. Si activa F # Interactivo de 64 bits en Tools -> Options -> F# Tools -> F# Interactive, puede observar el mismo comportamiento allí.

Diferrent de the other question, x64 la inestabilidad no es un problema. Resulta que "Generate tail calls" opción en la propiedad Proyecto causa una desaceleración considerable de test1 en comparación con test2. Si desactivas esa opción, dos casos tienen velocidades similares.

Por otro lado, puede utilizar la palabra clave inline en fun1 para que no se necesite una llamada final. Dos ejemplos son comparables en el tiempo de ejecución nuevamente, sin importar fun2 está en línea o no.

Dicho esto, es extraño que la adición de tail. código de operación a lo hace mucho más lento que (haciendo lo mismo con) fun2. Puede ponerse en contacto con el equipo F # para mayor investigación.

Cuestiones relacionadas