fannkuch-redux F# .NET Core #6 program
source code
// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// ported from C# version adding native by Anthony Lloyd
#nowarn "9"
open System
open System.Threading
open Microsoft.FSharp.NativeInterop
[<EntryPoint>]
let main args =
let n = if args.Length=0 then 7 else int args.[0]
let fact = Array.zeroCreate (n+1)
fact.[0] <- 1
let mutable factn = 1
for i = 1 to n do
factn <- factn * i
Array.set fact i factn
let inline firstPermutation p pp count idx =
for i = 0 to n-1 do NativePtr.set p i i
let rec loop i idx =
if i>0 then
let d = idx/Array.get fact i
NativePtr.set count i d
loop (i-1) <|
if d=0 then idx
else
for j = 0 to i do
NativePtr.get p j
|> NativePtr.set pp j
for j = 0 to i do
NativePtr.get pp ((j+d) % (i+1))
|> NativePtr.set p j
idx % fact.[i]
loop (n-1) idx
let inline nextPermutation p count =
let mutable first = NativePtr.get p 1
NativePtr.get p 0 |> NativePtr.set p 1
NativePtr.set p 0 first
let mutable i = 1
while let c =NativePtr.get count i+1 in NativePtr.set count i c; c>i do
NativePtr.set count i 0
i <- i+1
let next = NativePtr.get p 1
NativePtr.set p 0 next
for j = 1 to i-1 do NativePtr.get p (j+1) |> NativePtr.set p j
NativePtr.set p i first
first <- next
first
let inline countFlips first p pp =
if first=0 then 0
elif NativePtr.get p first=0 then 1
else
for i = 0 to n-1 do NativePtr.get p i |> NativePtr.set pp i
let rec loop flips first =
let rec swap lo hi =
if lo<hi then
let t = NativePtr.get pp lo
NativePtr.get pp hi |> NativePtr.set pp lo
NativePtr.set pp hi t
swap (lo+1) (hi-1)
swap 1 (first-1)
let tp = NativePtr.get pp first
if NativePtr.get pp tp=0 then flips
else
NativePtr.set pp first first
loop (flips+1) tp
loop 2 first
let chkSums = Array.zeroCreate Environment.ProcessorCount
let maxFlips = Array.zeroCreate Environment.ProcessorCount
let run n taskId taskSize =
use p = fixed &(Array.zeroCreate n).[0]
use pp = fixed &(Array.zeroCreate n).[0]
use count = fixed &(Array.zeroCreate n).[0]
firstPermutation p pp count (taskId*taskSize)
let rec loop i chksum maxflips =
if i=0 then chksum, maxflips
else
let flips = countFlips (nextPermutation p count) p pp
loop (i-1) (chksum + (1-(i%2)*2) * flips) (max flips maxflips)
let flips = countFlips (NativePtr.get p 0) p pp
let chksum, maxflips = loop (taskSize-1) flips flips
chkSums.[taskId] <- chksum
maxFlips.[taskId] <- maxflips
let taskSize = factn / Environment.ProcessorCount
let threads = Array.zeroCreate Environment.ProcessorCount
for i = 1 to Environment.ProcessorCount-1 do
let thread = Thread(fun () -> run n i taskSize)
thread.Start()
threads.[i] <- thread
run n 0 taskSize
let rec loop i chksum maxflips =
if i=threads.Length then chksum, maxflips
else
threads.[i].Join()
loop (i+1) (chksum+chkSums.[i]) (max maxflips maxFlips.[i])
let chksum, maxflips = loop 1 chkSums.[0] maxFlips.[0]
string chksum+"\nPfannkuchen("+string n+") = "+string maxflips
|> stdout.WriteLine
exit 0
notes, command-line, and program output
NOTES:
64-bit Ubuntu quad core
2.0.2 a04b4bf512
"System.GC.Server": true
Wed, 22 Nov 2017 02:55:36 GMT
MAKE:
cp fannkuchredux.fsharpcore-6.fsharpcore Program.fs
cp Include/fsharpcore/tmp.fsproj .
cp Include/fsharpcore/runtimeconfig.template.json .
mkdir obj
cp Include/fsharpcore/project.assets.json ./obj
cp Include/fsharpcore/tmp.fsproj.nuget.g.props ./obj
cp Include/fsharpcore/tmp.fsproj.nuget.g.targets ./obj
/usr/bin/dotnet build -c Release --no-restore
Microsoft (R) Build Engine version 15.4.8.50001 for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
tmp -> /home/dunham/benchmarksgame_quadcore/fannkuchredux/tmp/bin/Release/netcoreapp2.0/tmp.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:15.35
18.07s to complete and log all make actions
COMMAND LINE:
/usr/bin/dotnet ./bin/Release/netcoreapp2.0/tmp.dll 12
PROGRAM OUTPUT:
3968050
Pfannkuchen(12) = 65