Skip to content

Instantly share code, notes, and snippets.

@doublec
Created August 9, 2010 03:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save doublec/514898 to your computer and use it in GitHub Desktop.
Save doublec/514898 to your computer and use it in GitHub Desktop.
staload "libc/SATS/random.sats"
staload "libc/SATS/unistd.sats"
staload "libats/SATS/parworkshop.sats"
staload "libats/DATS/parworkshop.dats"
staload "prelude/DATS/array.dats"
#define ITER 100000000
#define NCPU 2
fn random_double (buf: &drand48_data): double = let
var r: double
val _ = drand48_r(buf, r)
in
r
end
fn attempts (buf: &drand48_data): int = let
fun loop (buf: &drand48_data, sum: double, count: int): int =
if sum <= 1.0 then loop(buf, sum + random_double(buf), count + 1) else count
in
loop(buf, 0.0, 0)
end
fun n_attempts (n:int): int = let
var buf: drand48_data
val _ = srand48_r(0L, buf)
fun loop (n:int, count: int, buf: &drand48_data):int =
if n = 0 then count else loop(n-1, count + attempts(buf), buf)
in
loop(n, 0, buf)
end
viewtypedef work = () -<lin,cloptr1> int
fun fwork {l:addr}
(ws: !WORKSHOPptr(work,l), x: &work >> work?): int = x()
fun insert_work {l2:agz}
{n:nat | n > 1}
{i:nat | i < n}
(ws: !WORKSHOPptr(work, l2),
arr: &(@[int][n]),
i: int i,
iterations: int):void = let
extern prfun __ref {l:addr} {n:nat} (pf: !array_v(int, n, l)): array_v(int, n, l)
extern prfun __unref {l:addr} {n:nat} (pf: array_v(int, n, l)):void
prval pf = __ref (view@ arr)
val () = workshop_insert_work(ws,
llam() => let
val () = arr[i] := n_attempts(iterations);
prval () = __unref(pf)
in 1 end)
in
()
end
implement main() = let
val ws = workshop_make<work>(NCPU, fwork)
var ncpu: int
val () = for(ncpu := 0; ncpu < NCPU; ncpu := ncpu + 1) let
val _ = workshop_add_worker(ws) in () end
val nworker = workshop_nworker_get(ws)
val (pf_gc_arr, pf_arr | arr) = array_ptr_alloc<int>(NCPU)
val () = array_ptr_initialize_elt<int>(!arr, NCPU, 0)
prval pf_arr = pf_arr
var i:Nat = 0;
val () = while(i < NCPU) let
val () = insert_work(ws, !arr, i, (ITER / NCPU))
in
i := i + 1
end
val () = workshop_wait_blocked_all(ws)
var j: Nat = 0;
val () = while(j < nworker) let
val () = workshop_insert_work(ws, llam() =<cloptr1> 0)
in
j := j + 1
end
val () = workshop_wait_quit_all(ws)
val () = workshop_free_vt_exn(ws)
var k: Nat = 0;
var total: int = 0;
val () = for(k := 0; k < NCPU; k := k + 1) total := total + arr[k]
val avg = total / double_of_int(ITER)
val () = printf("total: %d\n", @(total))
val () = print(avg)
in
array_ptr_free {int} (pf_gc_arr, pf_arr | arr)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment