// Learn more about F# at http://docs.microsoft.com/dotnet/fsharp
open BenchmarkDotNet.Attributes
open BenchmarkDotNet.Running
module DotProduct =
let rec dotProduct (vector1 : float []) (vector2 : float []) : float =
if vector1 |> Array.length = 0 then
0.0
else
vector1.[0] * vector2.[0] + (dotProduct (vector1 |> Array.tail) (vector2 |> Array.tail))
let dotProductLoop (vector1 : float []) (vector2 : float []) : float =
let mutable acc = 0.0
for idx = 0 to vector1.Length - 1 do
acc <- acc + (vector1.[idx] * vector2.[idx])
acc
// Fast
let dotProductFold (vector1 : float []) (vector2 : float []) =
Array.fold2 (fun state x y -> state + x * y) 0.0 vector1 vector2
[<MemoryDiagnoser>]
type DotProductBench() =
let arr1 = [| 1.0..1_000.0 |]
let arr2 = [| 1.0..1_000.0 |]
[<Benchmark(Baseline=true)>]
member _.DotProduct() = DotProduct.dotProduct arr1 arr2
[<Benchmark>]
member _.DotProductLoop() = DotProduct.dotProductLoop arr1 arr2
[<Benchmark>]
member _.DotProductFold() = DotProduct.dotProductFold arr1 arr2
[<EntryPoint>]
let main argv =
BenchmarkRunner.Run<DotProductBench>() |> ignore
0 // return an integer exit code
BenchmarkDotNet=v0.13.1, OS=Windows 10.0.19042.1288 (20H2/October2020Update)
AMD Ryzen 9 5900X, 1 CPU, 24 logical and 12 physical cores
.NET SDK=6.0.100-rc.2.21505.57
[Host] : .NET 6.0.0 (6.0.21.48005), X64 RyuJIT DEBUG
DefaultJob : .NET 6.0.0 (6.0.21.48005), X64 RyuJIT
Method |
Mean |
Error |
StdDev |
Ratio |
Gen 0 |
Gen 1 |
Allocated |
DotProduct |
320,534.9 ns |
1,738.55 ns |
1,626.24 ns |
1.000 |
480.4688 |
18.0664 |
8,040,000 B |
DotProductLoop |
625.4 ns |
1.93 ns |
1.71 ns |
0.002 |
- |
- |
- |
DotProductFold |
1,105.1 ns |
10.77 ns |
10.07 ns |
0.003 |
- |
- |
- |