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.
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.
Am I doing something wrong in my code?
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...
EDIT: Direct GitHub link, where the code lives in various language forms...
EDIT2: Thanks to Thomas and Daniel, speed improved considerably:
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: 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!)
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.
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
You can mark some trivial functions as inline
. For example:
let inline myincr (arr:int array) idx = arr.[idx] <- arr.[idx] + 1
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With