source code
// The Computer Language Benchmarks Game
// https://salsa.debian.org/benchmarksgame-team/benchmarksgame/
//
// Based on C# version by Isaac Gouy, The Anh Tran, Alan McGovern
// Contributed by Don Syme
open System
open System.Threading
type BarrierHandle(threads:int) =
let mutable current = threads
let mutable handle = new ManualResetEvent(false)
member x.WaitOne() =
let h = handle
if Interlocked.Decrement(¤t) > 0 then
h.WaitOne() |> ignore;
else
handle <- new ManualResetEvent(false);
Interlocked.Exchange(¤t, threads) |> ignore;
h.Set() |> ignore;
h.Dispose();
let Approximate(u:double[], v:double[], tmp:double[], rbegin, rend, barrier: BarrierHandle) =
let mutable vBv = 0.0
let mutable vv = 0.0
// return element i,j of infinite matrix A
let A i j = 1.0 / float((i + j) * (i + j + 1) / 2 + i + 1)
// multiply vector v by matrix A
let multiplyAv(v:double[], Av:double[]) =
for i = rbegin to rend - 1 do
let mutable sum = 0.0;
for j = 0 to v.Length - 1 do
sum <- sum + A i j * v.[j];
Av.[i] <- sum
// multiply vector v by matrix A transposed
let multiplyAtv(v:double[], atv:double[]) =
for i = rbegin to rend - 1 do
let mutable sum = 0.0
for j = 0 to v.Length - 1 do
sum <- sum + A j i * v.[j];
atv.[i] <- sum;
// multiply vector v by matrix A and then by matrix A transposed
let multiplyatAv(v:double[], tmp:double[], atAv:double[]) =
multiplyAv(v, tmp);
barrier.WaitOne();
multiplyAtv(tmp, atAv);
barrier.WaitOne();
for i = 0 to 9 do
multiplyatAv(u, tmp, v);
multiplyatAv(v, tmp, u);
for i = rbegin to rend - 1 do
vBv <- vBv + u.[i] * v.[i];
vv <- vv + v.[i] * v.[i];
(vBv, vv)
let RunGame n =
// create unit vector
let u = Array.create n 1.0
let tmp = Array.zeroCreate n
let v = Array.zeroCreate n
let nthread = Environment.ProcessorCount;
let barrier = new BarrierHandle(nthread);
// create thread and hand out tasks
let chunk = n / nthread;
// objects contain result of each thread
let aps =
Async.Parallel
[ for i in 0 .. nthread - 1 do
let r1 = i * chunk;
let r2 = if (i < (nthread - 1)) then r1 + chunk else n
yield async { return Approximate(u, v, tmp, r1, r2, barrier) } ]
|> Async.RunSynchronously
let vBv = aps |> Array.sumBy fst
let vv = aps |> Array.sumBy snd
Math.Sqrt(vBv / vv);
[<EntryPoint>]
let main args =
let n = try int <| args.[0] with _ -> 2500
System.Console.WriteLine("{0:f9}", RunGame n);
0
notes, command-line, and program output
NOTES:
64-bit Ubuntu quad core
.NET SDK 9.0.100
Host Version: 9.0.0
Commit: 9d5a6a9aa4
<OutputType>Exe
<TargetFramework>net9.0
<ImplicitUsings>enable
<Nullable>enable
<AllowUnsafeBlocks>true
<ServerGarbageCollection>true
<ConcurrentGarbageCollection>true
<PublishAot>false
Thu, 06 Feb 2025 11:05:58 GMT
MAKE:
cp spectralnorm.fsharpcore-2.fsharpcore Program.fs
cp Include/fsharpcore/program.fsproj .
/opt/src/dotnet-sdk-9.0.100/dotnet build -r linux-x64 -c Release
Determining projects to restore...
Restored /home/dunham/all-benchmarksgame/benchmarksgame_i53330/spectralnorm/tmp/program.fsproj (in 721 ms).
program -> /home/dunham/all-benchmarksgame/benchmarksgame_i53330/spectralnorm/tmp/bin/Release/net9.0/linux-x64/program.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:10.22
12.01s to complete and log all make actions
COMMAND LINE:
./bin/Release/net9.0/linux-x64/program 5500
PROGRAM OUTPUT:
1.274224153