ético verificar revista pensamiento para lecturas horas gubernamental etica ethos desarrollo certificacion centro acceso performance f# benchmarking

performance - verificar - revista ethos



F#parece más lento que otros idiomas... ¿qué puedo hacer para acelerarlo? (2)

Me gusta F #; Realmente, realmente lo hago Habiendo sido mordido por la "programación funcional" -bug, me obligo a usarlo cuando tengo la oportunidad de hacerlo. De hecho, recientemente lo utilicé (durante unas vacaciones de una semana) para codificar un buen algoritmo de inteligencia artificial .

Sin embargo, mis intentos hasta ahora (ver una pregunta ASÍ relacionada con mi primer intento aquí ) parecen indicar que, aunque sin duda hermosa ... F # tiene la velocidad de ejecución más lenta de todos los idiomas que he usado.

¿Estoy haciendo algo mal en mi código?

Explico ampliamente lo que hice en mi blog , y en mis experimentos, veo que OCaml y el resto del grupo se ejecutan desde 5x hasta 35x más rápido que F #.

¿Soy el único con tales experiencias? Encuentro desalentador que el lenguaje que más me gusta sea también el más lento, a veces por mucho ...

EDIT : enlace Direct GitHub, donde el código vive en varias formas de lenguaje ...

EDIT2 : Gracias a Thomas y Daniel, la velocidad mejoró considerablemente:

  • Mayor impulso de velocidad: pasando de "ref" a "mutable" dio un enorme 30%.
  • Eliminar excepciones y usar while / flagChecks dio otro 16%.
  • Pasar de las uniones discriminadas a las enumeraciones dio otro 5%.
  • "en línea" dio 0.5-1%

EDIT3 : El Dr. Jon Harrop se unió a la lucha: 60% de aceleración, haciendo que ScoreBoard opere directamente en la versión "enumerada" de los datos. La versión imperativa de F # ahora se ejecuta 3-4 veces más lenta que C ++, que es un buen resultado para un tiempo de ejecución basado en VM. Considero el problema resuelto, ¡gracias chicos!

EDIT4 : Después de fusionar todas las optimizaciones, estos son los resultados (F # llegó a C # en estilo imperativo, ¡ahora si solo pudiera hacer algo sobre estilo funcional también!)

  • 0m0.221s reales: Eso fue C ++
  • 0m0.676s reales: Eso fue C # (imperativo, espejo C ++)
  • 0m0.704s reales: Eso fue F # (imperativo, espejo de C ++)
  • 0m0.753s reales: Eso fue OCaml (imperativo, espejo C ++)
  • real 0m0.989s: Eso fue OCaml (funcional)
  • 0m1.064s reales: Eso fue Java (imperativo)
  • 0m1.955s reales: Eso fue F # (funcional)

A menos que pueda dar una muestra de código de un tamaño razonable, es difícil de decir. De todos modos, la versión imperativa de F # debe ser tan eficiente como la versión imperativa de C #. Creo que un enfoque es comparar los dos para ver qué está causando la diferencia (entonces alguien puede ayudar a hacer que ese bit sea más rápido).

Miré brevemente su código y aquí hay algunas sugerencias variadas (no probadas).

  • Puede reemplazar la Cell unión discriminada con una enumeración (esto significa que usará tipos de valores y una comparación entera en lugar de tipos de referencia y pruebas de tipo de tiempo de ejecución):

    type Cell = | Orange = 1 | Yellow = 2 | Barren = 3

  • Puede marcar algunas funciones triviales como en inline . Por ejemplo:

    let inline myincr (arr:int array) idx = arr.[idx] <- arr.[idx] + 1

  • No use excepciones para control-flujo. Esto se hace a menudo en OCaml, pero las excepciones de .NET son lentas y solo deberían usarse para excepciones . Puede reemplazar el bucle for en su muestra con un bucle while y un flag mutable o con una función recursiva de cola (una función recursiva de cola se compila en un bucle, por lo que será eficiente, incluso en una solución imperativa).


Esta no es una respuesta, per se, pero ¿ha intentado escribir exactamente el mismo código en F # y C #, es decir, en el código imperativo F #? La velocidad debe ser similar. Si está comparando el código funcional breve con el uso intensivo de funciones de orden superior, expresiones de secuencia, valores diferidos, concordancia compleja de patrones, etc., todas las cosas que permiten un código más corto, más claro (lectura, más fácil de mantener), bueno, a menudo hay una compensación. En general, el tiempo de desarrollo / mantenimiento es mucho mayor que el tiempo de ejecución, por lo que generalmente se considera una compensación deseable .

Algunas referencias:
El CLR de F # y C # es el mismo, entonces, ¿por qué F # es más rápido que C #?
C # / F # Comparación de rendimiento
https://.com/questions/142985/is-a-program-f-any-more-efficient-execution-wise-than-c

Otro punto a considerar: en un lenguaje funcional estás trabajando en un nivel superior y es muy fácil pasar por alto los costos de las operaciones. Por ejemplo, Seq.sort parece bastante inocente, pero su uso ingenuo puede condenar al rendimiento. Recomiendo estudiar detenidamente su código, preguntándose por el camino si comprende el costo de cada operación. Si no te sientes reflexivo, una forma más rápida de hacerlo es, por supuesto, con un generador de perfiles.