F#似乎比其他语言慢......我能做些什么来加快速度?

tts*_*ras 27 performance benchmarking f#

我喜欢F#; 我真的,真的.被"函数式编程"咬了之后,我强迫自己在有机会的时候使用它.事实上,我最近使用它(在一个星期的休假期间)来编写一个很好的AI算法.

但是,我尝试到目前为止(见与我第一次尝试一个SO问题在这里)似乎表明,虽然无疑是美丽的...... F#有我用过的所有语言中最慢的执行速度.

我在代码中做错了吗?

我在博客文章中详细解释了我的所作所为,在我的实验中,我看到OCaml和其他组的运行速度比F#快5到35倍.

我是唯一一个有这种经历的人吗?我觉得令人沮丧的是,我最喜欢的语言也是最慢的 - 有时到目前为止......

编辑:直接GitHub链接,代码以各种语言形式存在...

编辑2:感谢托马斯和丹尼尔,速度大大提高:

  • 最大的速度提升:从"参考"转变为"可变"提供了高达30%的速度.
  • 删除异常并使用while/flagChecks给了另外16%.
  • 从歧视的工会转向枚举,又增加了5%.
  • "内联"给出了0.5-1%

编辑3:Jon Harrop博士加入了战斗:60%的加速,使得ScoreBoard直接在"枚举"版本的数据上运行.现在,F#的命令版本运行速度比C++慢3-4倍,这对于基于VM的运行时来说是一个很好的结果.我认为问题解决了 - 谢谢你们!

EDIT4:在合并所有优化之后,这些就是结果(F#以命令式的方式达到C# - 现在,如果我只能做一些关于功能风格的话!)

  • 真正的0m0.221s:那是C++
  • 真正的0m0.676s:那是C#(命令式,C++镜像)
  • 真正的0m0.704s:那是F#(命令式,C++镜像)
  • 真正的0m0.753s:那是OCaml(命令式,C++镜像)
  • 真正的0m0.989s:那是OCaml(功能)
  • 真正的0m1.064s:那是Java(势在必行)
  • 真正的0m1.955s:那是F#(功能)

Tom*_*cek 16

除非您能提供合理大小的代码示例,否则很难说清楚.无论如何,命令式F#版本应该与命令式C#版本一样高效.我认为一种方法是对两者进行基准测试,看看是什么导致了差异(然后有人可以帮助提高这一点).

我简要地查看了您的代码,这里有一些(未经测试的)建议.

  • 您可以Cell使用枚举替换区别联合(这意味着您将使用值类型和整数比较而不是引用类型和运行时类型测试):

    type Cell =    
      | Orange = 1
      | Yellow = 2
      | Barren = 3
    
    Run Code Online (Sandbox Code Playgroud)
  • 你可以将一些琐碎的功能标记为inline.例如:

    let inline myincr (arr:int array) idx =
      arr.[idx] <- arr.[idx] + 1
    
    Run Code Online (Sandbox Code Playgroud)
  • 不要使用控制流的异常.这通常在OCaml中完成,但.NET异常很慢,应该只用于异常.您可以替换for与您的样品中环while环和一个可变的标志或用尾递归函数(一尾递归函数编译成一个圈,所以这将是有效的,甚至在必要的解决方案).


Dan*_*iel 12

这本身不是一个答案,但您是否尝试在F#和C#中编写完全相同的代码,即命令式F#代码?速度应该相似.如果您正在比较简洁的功能代码,大量使用高阶函数,序列表达式,惰性值,复杂模式匹配等等 - 所有允许更短,更清晰(读取,更易维护)代码的东西 - 嗯,经常需要权衡.通常,开发/维护时间远远大于执行时间,因此通常被认为是理想的权衡.

一些参考文献:
F#和C#的CLR相同,那么为什么F#比C#更快
#/ F#性能比较
/sf/ask/10008981/ -wise-比-C

需要考虑的另一点是:在功能语言中,您正在更高层次上工作,而且很容易忽视运营成本.例如,Seq.sort看起来足够无辜,但天真地使用它可能会导致性能下降.我建议仔细研究你的代码,如果你了解每项操作的成本,就要问自己.如果你没有反思,那么更快的方法就是使用剖析器.

  • @ttsiodras:很酷.我仍然建议分析,直到它与C#相提并论.必须有一个差异的原因.[这里](http://eqatec.com/Profiler/Download.aspx)是免费的. (4认同)
  • 对不起,我想我很懒,我不是在读一篇_long_博客文章.;-)感谢您的链接. (2认同)