As it turns out algorithms coded in F# code might have much better performance, compared to the ones in C# code.

Below you will find F# version of optimized sigma-comparison algorithm from the previous post.

Compared to the C#, this .NET code:

- executes sigmoid1 benchmark in
**588.8ms instead of 3899,2ms** - executes sigmoid2 (LUT) benchmark in
**156.6ms instead of 411.4ms**

You’ll see below that this performance of F# is quite close to the performance of the similar implementation written in C.

Here’s the F# code:

```
#light
let Scale = 320.0f;
let Resolution = 2047;
let Min = -single(Resolution)/Scale;
let Max = single(Resolution)/Scale;
let range step a b =
let count = int((b-a)/step);
seq { for i in 0 .. count -> single(i)*step + a };
let lut = [|
for x in 0 .. Resolution ->
single(1.0/(1.0 + exp(-double(x)/double(Scale))))
|]
let sigmoid1 value = 1.0f/(1.0f + exp(-value));
let sigmoid2 v =
if (v <= Min) then 0.0f;
elif (v>= Max) then 1.0f;
else
let f = v * Scale;
if (v>0.0f) then lut.[int (f + 0.5f)]
else 1.0f - lut.[int(0.5f - f)];
let getError f =
let test = range 0.00001f -10.0f 10.0f;
let errors = seq {
for v in test ->
abs(sigmoid1(single(v)) - f(single(v)))
}
Seq.max errors;
open System.Diagnostics;
let test f =
let sw = Stopwatch.StartNew();
let mutable m = 0.0f;
let result =
for t in 1 .. 10 do
for x in 1 .. 1000000 do
m <- f(single(x)/100000.0f-5.0f);
sw.Elapsed.TotalMilliseconds;
printf "Max deviation is %f\n" (getError sigmoid2)
printf "10^7 iterations using sigmoid1: %f ms\n" (test sigmoid1)
printf "10^7 iterations using sigmoid2: %f ms\n" (test sigmoid2)
let c = System.Console.ReadKey(true);
```

And the output (Release compilation against F# 1.9.6.2 CTP with no debugger):

```
Max deviation is 0.001664
10^7 iterations using sigmoid1: 588.843700 ms
10^7 iterations using sigmoid2: 156.626700 ms
```

Chances are that the performance of sigmoid2 is better than that, but I just can’t figure out how to get rid of the mutable state.

# Running as Mono

By the way, that’s how similar (although not exact) code works out under Mono (details):

```
$ gmcs test.cs && mono test.exe
Max detected error using LUT: 0.1568425 %
1000000 iterations using Sigmoid1() took 3591.858 ms
1000000 iterations using Sigmoid2() took 247.561 ms
```

# Running as C

C is supposed to be really close to metal and highly efficient. Let’s check out how it works out for this algorithm.

Running C implementation of the code (developed by Henrik Gustafsson) yields following results:

```
Max deviation is 0.001664
10^7 iterations using sigmoid1: 628 ms
10^7 iterations using sigmoid2: 157 ms
```

Surprisingly enough, the performance is almost the same as F#. So F# must be doing really good job here.

Caveat: I’ve been using win32 compiler to get the binaries. 64 bit might improve the performance a bit. I’ll update the article if it does.

# Summary

So it turns out that F# compiler creates code that is 2-6 times faster for the math code, compared to C# (while the output is still .NET compatible). And this F# code has performance close to the one of the C code.

All this makes me wonder, if it is worth switching to F# for the core NeuroEvolution code. Stay tuned for the series.