From a2ca00808cf4ba7b4fda1c2557dc5a0e5028db1f Mon Sep 17 00:00:00 2001 From: KC Sivaramakrishnan Date: Tue, 14 Jun 2022 03:45:23 +0530 Subject: [PATCH] Update README.md --- README.md | 105 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 78 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 2ceba2a..32c23e0 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,98 @@ -# domainslib - Parallel Programming over Multicore OCaml +# Domainslib - Nested-parallel programming -`domainslib` provides control and data structure for parallel programming using -domains. +Domainslib provides support for nested-parallel programming. Domainslib provides async/await mechanism for spawning parallel tasks and awaiting their results. On top of this mechanism, domainslib provides parallel iteration functions. At its core, domainslib has an efficient implementation of work-stealing queue in order to efficiently share tasks with other domains. -The supported data structures are: +Here is a _sequential_ program that computes nth Fibonacci number using recursion: -* [Channels](https://github.com/ocaml-multicore/domainslib/blob/master/lib/chan.mli) - + Channels may be shared between multiple senders and receivers. - + Channels ensure FIFO message order. - + Channels come in two flavours -- bounded (fixed-buffer size (>= 0) beyond which the - send blocks) and unbounded. -* [Task](https://github.com/ocaml-multicore/domainslib/blob/master/lib/task.mli) - + Work-stealing task pool with async/await parallelism and parallel for loop. +```ocaml +(* fib.ml *) +let n = try int_of_string Sys.argv.(1) with _ -> 1 -See -[examples](https://github.com/ocaml-multicore/domainslib/tree/master/test) -for usage. +let rec fib n = if n < 2 then 1 else fib (n - 1) + fib (n - 2) -## Installation +let main () = + let r = fib n in + Printf.printf "fib(%d) = %d\n%!" n r + +let _ = main () +``` + +We can parallelise this program using Domainslib: + +```ocaml +(* fib_par.ml *) +let num_domains = try int_of_string Sys.argv.(1) with _ -> 1 +let n = try int_of_string Sys.argv.(2) with _ -> 1 + +(* Sequential Fibonacci *) +let rec fib n = + if n < 2 then 1 else fib (n - 1) + fib (n - 2) + +module T = Domainslib.Task + +let rec fib_par pool n = + if n > 20 then begin + let a = T.async pool (fun _ -> fib_par pool (n-1)) in + let b = T.async pool (fun _ -> fib_par pool (n-2)) in + T.await pool a + T.await pool b + end else + (* Call sequential Fibonacci if the available work is small *) + fib n + +let main () = + let pool = T.setup_pool ~num_additional_domains:(num_domains - 1) () in + let res = T.run pool (fun _ -> fib_par pool n) in + T.teardown_pool pool; + Printf.printf "fib(%d) = %d\n" n res + +let _ = main () +``` -The library can be installed using -[`multicore-opam`](https://github.com/ocaml-multicore/multicore-opam), an OPAM -repository of multicore specific packages. +The parallel program scales nicely compared to the sequential version. The results presented below were obtained on a 2.3 GHz Quad-Core Intel Core i7 MacBook Pro with 4 cores and 8 hardware threads. ```bash -$ opam switch create 4.12.0+domains+effects -$ opam install domainslib +$ hyperfine './fib.exe 42' './fib_par.exe 2 42' \ + './fib_par.exe 4 42' './fib_par.exe 8 42' +Benchmark 1: ./fib.exe 42 + Time (mean ± sd): 1.217 s ± 0.018 s [User: 1.203 s, System: 0.004 s] + Range (min … max): 1.202 s … 1.261 s 10 runs + +Benchmark 2: ./fib_par.exe 2 42 + Time (mean ± sd): 628.2 ms ± 2.9 ms [User: 1243.1 ms, System: 4.9 ms] + Range (min … max): 625.7 ms … 634.5 ms 10 runs + +Benchmark 3: ./fib_par.exe 4 42 + Time (mean ± sd): 337.6 ms ± 23.4 ms [User: 1321.8 ms, System: 8.4 ms] + Range (min … max): 318.5 ms … 377.6 ms 10 runs + +Benchmark 4: ./fib_par.exe 8 42 + Time (mean ± sd): 250.0 ms ± 9.4 ms [User: 1877.1 ms, System: 12.6 ms] + Range (min … max): 242.5 ms … 277.3 ms 11 runs + +Summary + './fib_par2.exe 8 42' ran + 1.35 ± 0.11 times faster than './fib_par.exe 4 42' + 2.51 ± 0.10 times faster than './fib_par.exe 2 42' + 4.87 ± 0.20 times faster than './fib.exe 42' ``` -## Development +More example programs are available [here](https://github.com/ocaml-multicore/domainslib/tree/master/test). -If you are interested in hacking on the implementation, then `opam pin` this -repository: +## Installation + +You can install this library using `OPAM`. -First install the multicore compiler and dune: ```bash -$ opam switch create 4.12.0+domains+effects -$ opam install dune +$ opam switch create 5.0.0+trunk --repo=default,alpha=git+https://github.com/kit-ty-kate/opam-alpha-repository.git +$ opam install domainslib ``` -Then, pin a clone of this repo: +## Development + +If you are interested in hacking on the implementation, then `opam pin` this repository: ```bash +$ opam switch create 5.0.0+trunk --repo=default,alpha=git+https://github.com/kit-ty-kate/opam-alpha-repository.git $ git clone https://github.com/ocaml-multicore/domainslib $ cd domainslib $ opam pin add domainslib file://`pwd`