package moonpool

  1. Overview
  2. Docs

Fork-join primitives.

NOTE These are only available on OCaml 5.0 and above.

  • since 0.3
val both : (unit -> 'a) -> (unit -> 'b) -> 'a * 'b

both f g runs f() and g(), potentially in parallel, and returns their result when both are done. If any of f() and g() fails, then the whole computation fails.

This must be run from within the pool: for example, inside Pool.run or inside a Fut.spawn computation. This is because it relies on an effect handler to be installed.

  • since 0.3

NOTE this is only available on OCaml 5.

val both_ignore : (unit -> _) -> (unit -> _) -> unit

Same as both f g |> ignore.

  • since 0.3

NOTE this is only available on OCaml 5.

val for_ : ?chunk_size:int -> int -> (int -> int -> unit) -> unit

for_ n f is the parallel version of for i=0 to n-1 do f i done.

f is called with parameters low and high and must use them like so:

for j = low to high do (* … actual work *) done 

. If chunk_size=1 then low=high and the loop is not actually needed.

  • parameter chunk_size

    controls the granularity of parallelism. The default chunk size is not specified. See all_array or all_list for more details.

    Example:

    let total_sum = Atomic.make 0
    
    let() = for_ ~chunk_size:5 100
      (fun low high ->
        (* iterate on the range sequentially. The range should have 5 items or less. *)
        let local_sum = ref 0 in
        for j=low to high do
          local_sum := !local_sum + j
        done;
        ignore (Atomic.fetch_and_add total_sum !local_sum : int)))
    
    let() = assert (Atomic.get total_sum = 4950)

    Note how we still compute a local sum sequentially in (fun low high -> …), before combining it wholesale into total_sum. When the chunk size is large, this can have a dramatic impact on the synchronization overhead.

    When chunk_size is not provided, the library will attempt to guess a value that keeps all cores busy but runs as few tasks as possible to reduce the synchronization overhead.

    Use ~chunk_size:1 if you explicitly want to run each iteration of the loop in its own task.

  • since 0.3

NOTE this is only available on OCaml 5.

val all_array : ?chunk_size:int -> (unit -> 'a) array -> 'a array

all_array fs runs all functions in fs in tasks, and waits for all the results.

  • parameter chunk_size

    if equal to n, groups items by n to be run in a single task. Default is 1.

  • since 0.3

NOTE this is only available on OCaml 5.

val all_list : ?chunk_size:int -> (unit -> 'a) list -> 'a list

all_list fs runs all functions in fs in tasks, and waits for all the results.

  • parameter chunk_size

    if equal to n, groups items by n to be run in a single task. Default is not specified. This parameter is available since 0.3.

  • since 0.3

NOTE this is only available on OCaml 5.

val all_init : ?chunk_size:int -> int -> (int -> 'a) -> 'a list

all_init n f runs functions f 0, f 1, … f (n-1) in tasks, and waits for all the results.

  • parameter chunk_size

    if equal to n, groups items by n to be run in a single task. Default is not specified. This parameter is available since 0.3.

  • since 0.3

NOTE this is only available on OCaml 5.

val map_array : ?chunk_size:int -> ('a -> 'b) -> 'a array -> 'b array

map_array f arr is like Array.map f arr, but runs in parallel.

  • since 0.3

NOTE this is only available on OCaml 5.

val map_list : ?chunk_size:int -> ('a -> 'b) -> 'a list -> 'b list

map_list f l is like List.map f l, but runs in parallel.

  • since 0.3

NOTE this is only available on OCaml 5.