F# 似乎比其他语言慢...我能做些什么来加快速度? [英] F# seems slower than other languages... what can I do to speed it up?

查看:22
本文介绍了F# 似乎比其他语言慢...我能做些什么来加快速度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I like F# ; I really, really do. Having been bitten by the "functional programming"-bug, I force myself to use it when I have the opportunity to. In fact, I recently used it (during a one week vacation) to code a nice AI algorithm.

但是,到目前为止,我的尝试(请参阅与我的第一次尝试相关的 SO 问题 here) 似乎表明,尽管无疑很漂亮……在我使用过的所有语言中,F# 的执行速度是最慢的.

However, my attempts so far (see a SO question related to my first attempt here) seem to indicate that, though undoubtedly beautiful... F# has the slowest execution speed of all the languages I've used.

我的代码做错了吗?

我在我的博文中详细解释了我所做的事情,以及在我的实验中,我看到 OCaml 和其他组的运行速度比 F# 快 5 到 35 倍.

I verbosely explain what I did in my blog post, and in my experiments, I see OCaml and the rest of the group running anywhere from 5x to 35x faster than F#.

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

Am I the only one with such experiences? I find it disheartening that the language I like the most, is also the slowest one - sometimes by far...

编辑:直接 GitHub 链接,代码所在的位置在各种语言形式...

EDIT: Direct GitHub link, where the code lives in various language forms...

EDIT2:感谢 Thomas 和 Daniel,速度大大提高:

EDIT2: Thanks to Thomas and Daniel, speed improved considerably:

  • 最大的速度提升:从ref"到mutable"的速度提高了 30%.
  • 删除异常并使用 while/flagChecks 又得到了 16%.
  • 从受歧视的联合转换为枚举又增加了 5%.
  • 内联"给了 0.5-1%

EDIT3:Jon Harrop 博士加入了战斗:通过让 ScoreBoard 直接对数据的枚举"版本进行操作,速度提高了 60%.F# 的命令式版本现在运行速度比 C++ 慢 3-4 倍,这对于基于 VM 的运行时来说是一个很好的结果.我认为问题已解决 - 谢谢大家!

EDIT3: Dr Jon Harrop joined the fight: 60% speedup, by making ScoreBoard operate directly on the "enumerated" version of the data. The imperative version of F# now runs 3-4 times slower than C++, which is a good result for a VM-based runtime. I consider the problem solved - thanks guys!

EDIT4:合并所有优化后,结果如下(F# 以命令式风格达到 C# - 现在,如果我也能对函数式风格做点什么就好了!)

EDIT4: After merging all optimizations, these are the results (F# reached C# in imperative style - now if only I could do something about functional style, too!)

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

推荐答案

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

Unless you can give a reasonably sized code sample, it's difficult to tell. Anyway, the imperative F# version should be as efficient as the imperative C# version. I think one approach is to benchmark the two to see what is causing the difference (then someone can help with making that bit faster).

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

I briefly looked at your code and here are some assorted (untested) suggestions.

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

  • You can replace discriminated union Cell with an enum (this means you'll use value types and integer comparison instead of reference types and runtime type tests):

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 循环和可变标志或尾递归函数(尾递归函数被编译为循环,因此即使在命令式解决方案中也是有效的).

  • Don't use exceptions for control-flow. This is often done in OCaml, but .NET exceptions are slow and should be only used for exceptions. You can replace the for loop in your sample with a while loop and a mutable flag or with a tail-recursive function (a tail-recursive function is compiled into a loop, so it will be efficient, even in imperative solution).

    这篇关于F# 似乎比其他语言慢...我能做些什么来加快速度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆