Reputation: 15562
I'm trying to parallelize work. I'm trying to have subprocesses each take a piece of the work, then wait for the work to complete from the parent process.
The following solution seems to work for small examples:
let par_iter (items: 'i list) ~(f: 'i -> unit): unit =
let orig_pid = Unix.getpid () in
let rec loop = function
| [] -> ()
| h :: t ->
match Unix.fork () with
| 0 -> f h
| _ -> loop t
in
loop items;
if Unix.getpid () = orig_pid then
List.iter items ~f:(fun _ -> ignore @@ Unix.wait ())
else
exit 0
Usage:
let () =
par_iter [1; 2; 3; 4] ~f:do_something_with_an_int;
The contract of Unix.wait
when there are multiple subprocesses is not very clear to me. Here I'm relying on the behavior where wait
ing n
times will wait for all and only n
subprocesses to finish.
Does this solution rely on undefined behavior? Is there an alternative way to correctly implement par_iter
such that it spawns work on child processes and waits for the work to finish?
tested on OCaml 4.14.0
Upvotes: 1
Views: 144
Reputation: 66823
If the original parent process already had some subprocesses, this can fail. Thus, IMHO it's not usable as a general library. You should use Unix.waitpid
to wait specifically for the processes you created.
Upvotes: 2