我喜欢F#;我真的,真的。被“函数式编程”咬了之后,我强迫自己在有机会的时候使用它。事实上,我最近使用它(在一周休假期间)到code a nice AI algorithm。
然而,到目前为止我的尝试(看到与我的第一次尝试有关的问题here)似乎表明,虽然无疑是美丽的...... F#的执行速度是我用过的所有语言中最慢的
我在代码中做错了什么?
我详细解释了我在blog post中所做的事情,在我的实验中,我看到OCaml和其他人在比F#快5到35倍的任何地方运行。
我是唯一一个有这种经历的人吗?我觉得令人沮丧的是,我最喜欢的语言也是最慢的 - 有时到目前为止......
编辑:以各种语言形式直接使用GitHub链接where the code lives ...
EDIT2 :感谢Thomas和Daniel,速度有了很大提升:
EDIT3 :Jon Harrop博士加入了战斗:60%的加速,让ScoreBoard直接在“枚举”版本的数据上运行。现在,F#的命令版本运行速度比C ++慢3-4倍,这对于基于VM的运行时来说是一个很好的结果。我认为问题已经解决了 - 谢谢你们!
EDIT4 :在合并所有优化之后,结果就是这些(F#以命令式方式达到了C# - 现在,如果我只能做一些关于功能风格的事情呢!)
答案 0 :(得分:15)
除非您能提供合理大小的代码示例,否则很难说清楚。无论如何,命令式F#版本应该与命令式C#版本一样高效。我认为一种方法是对两者进行基准测试,看看是什么导致了差异(然后有人可以帮助提高这一点)。
我简要地查看了您的代码,这里有一些(未经测试的)建议。
您可以使用枚举替换歧视联合Cell
(这意味着您将使用值类型和整数比较而不是引用类型和运行时类型测试):
type Cell =
| Orange = 1
| Yellow = 2
| Barren = 3
您可以将一些简单的函数标记为inline
。例如:
let inline myincr (arr:int array) idx =
arr.[idx] <- arr.[idx] + 1
不要对控制流使用异常。这通常在OCaml中完成,但.NET异常很慢,应该只用于例外。您可以使用for
循环和可变标志或尾递归函数替换样本中的while
循环(尾递归函数被编译成循环,因此它将是高效的,即使在必要的解决方案中)。
答案 1 :(得分:12)
这本身不是一个答案,但您是否尝试在F#和C#中编写完全相同的代码,即命令式F#代码?速度应该相似。如果您正在比较简洁的功能代码,大量使用高阶函数,序列表达式,惰性值,复杂模式匹配等等 - 所有允许更短,更清晰(读取,更易维护)代码的东西 - 嗯,经常需要权衡。通常,开发/维护时间远远大于执行时间,因此它通常被认为是理想的权衡。
一些参考文献:
F# and C# 's CLR is same then why is F# faster than C#
C# / F# Performance comparison
https://stackoverflow.com/questions/142985/is-a-program-f-any-more-efficient-execution-wise-than-c
需要考虑的另一点:在功能语言中,您正在更高层次上工作,而且很容易忽略运营成本。例如,Seq.sort
似乎是无辜的,但天真地使用它可能会导致性能下降。我建议仔细研究你的代码,如果你了解每项操作的成本,就要问自己。如果你没有反思,那么更快的方法就是使用剖析器。