Effect Handlers in Multicore OCaml Daniel Hillerström, Daan Leijen, Sam Lindley, Matija Pretnar, Andreas Rossberg, KC Sivaramakrishnan
Effect Handlers • Multicore OCaml is an OCaml extension with native support for concurrency and shared-memory parallelism ✦ Concurrency expressed through effect handlers ✦ Will land upstream in Q2 2021
Effect Handlers • Multicore OCaml is an OCaml extension with native support for concurrency and shared-memory parallelism ✦ Concurrency expressed through effect handlers ✦ Will land upstream in Q2 2021 effect E : string let comp () = print_string "0 "; print_string (perform E); print_string "3 " let main () = try comp () with effect E k -> print_string "1 "; continue k "2 "; print_string “4 "
Effect Handlers • Multicore OCaml is an OCaml extension with native support for concurrency and shared-memory parallelism ✦ Concurrency expressed through effect handlers ✦ Will land upstream in Q2 2021 effect E : string let comp () = effect declaration print_string "0 "; print_string (perform E); print_string "3 " let main () = try comp () with effect E k -> print_string "1 "; continue k "2 "; print_string “4 "
Effect Handlers • Multicore OCaml is an OCaml extension with native support for concurrency and shared-memory parallelism ✦ Concurrency expressed through effect handlers ✦ Will land upstream in Q2 2021 effect E : string let comp () = effect declaration print_string "0 "; print_string (perform E); print_string "3 " computation let main () = try comp () with effect E k -> print_string "1 "; continue k "2 "; print_string “4 "
Effect Handlers • Multicore OCaml is an OCaml extension with native support for concurrency and shared-memory parallelism ✦ Concurrency expressed through effect handlers ✦ Will land upstream in Q2 2021 effect E : string let comp () = effect declaration print_string "0 "; print_string (perform E); print_string "3 " computation let main () = try comp () with effect E k -> handler print_string "1 "; continue k "2 "; print_string “4 "
Effect Handlers • Multicore OCaml is an OCaml extension with native support for concurrency and shared-memory parallelism ✦ Concurrency expressed through effect handlers ✦ Will land upstream in Q2 2021 effect E : string suspends current let comp () = effect declaration print_string "0 "; computation print_string (perform E); print_string "3 " computation let main () = try comp () with effect E k -> handler print_string "1 "; continue k "2 "; print_string “4 "
Effect Handlers • Multicore OCaml is an OCaml extension with native support for concurrency and shared-memory parallelism ✦ Concurrency expressed through effect handlers ✦ Will land upstream in Q2 2021 effect E : string suspends current let comp () = effect declaration print_string "0 "; computation print_string (perform E); print_string "3 " computation let main () = delimited continuation try comp () with effect E k -> handler print_string "1 "; continue k "2 "; print_string “4 "
Effect Handlers • Multicore OCaml is an OCaml extension with native support for concurrency and shared-memory parallelism ✦ Concurrency expressed through effect handlers ✦ Will land upstream in Q2 2021 effect E : string suspends current let comp () = effect declaration print_string "0 "; computation print_string (perform E); print_string "3 " computation let main () = delimited continuation try comp () with effect E k -> handler print_string "1 "; continue k "2 "; resume suspended print_string “4 " computation
Compilation effect E : string let comp () = print_string "0 "; print_string (perform E); print_string "3 " main let main () = pc try comp () with effect E k -> print_string "1 "; continue k "2 "; print_string “4 " sp
Compilation effect E : string let comp () = print_string "0 "; print_string (perform E); print_string "3 " main let main () = try pc comp () with effect E k -> print_string "1 "; continue k "2 "; print_string “4 " sp
Compilation parent effect E : string let comp () = comp print_string "0 "; print_string (perform E); print_string "3 " sp main let main () = try pc comp () with effect E k -> print_string "1 "; continue k "2 "; print_string “4 "
Compilation parent effect E : string let comp () = comp print_string "0 "; pc print_string (perform E); print_string "3 " comp main let main () = try comp () with effect E k -> sp print_string "1 "; continue k "2 "; print_string “4 " 0
Compilation parent effect E : string let comp () = comp print_string "0 "; pc print_string (perform E); print_string "3 " comp main let main () = try comp () with effect E k -> print_string "1 "; continue k "2 "; print_string “4 " sp 0
Compilation effect E : string let comp () = comp print_string "0 "; pc print_string (perform E); print_string "3 " comp main let main () = try comp () with effect E k -> print_string "1 "; continue k "2 "; print_string “4 " sp k 0
Compilation effect E : string let comp () = comp print_string "0 "; print_string (perform E); print_string "3 " comp main let main () = try comp () with effect E k -> pc print_string "1 "; continue k "2 "; print_string “4 " sp k 0
Compilation effect E : string let comp () = comp print_string "0 "; print_string (perform E); print_string "3 " comp main let main () = try comp () with effect E k -> print_string "1 "; pc continue k "2 "; print_string “4 " sp k 0 1
Compilation effect E : string let comp () = comp print_string "0 "; print_string (perform E); print_string "3 " comp main let main () = try comp () with effect E k -> print_string "1 "; pc continue k "2 "; print_string “4 " sp k 0 1
Compilation parent effect E : string let comp () = comp print_string "0 "; print_string (perform E); print_string "3 " comp main let main () = try comp () with effect E k -> sp print_string "1 "; pc continue k "2 "; print_string “4 " k 0 1
Compilation parent effect E : string let comp () = comp print_string "0 "; print_string (perform E); pc print_string "3 " comp main let main () = try comp () with effect E k -> sp print_string "1 "; continue k "2 "; print_string “4 " k 0 1 2
Compilation effect E : string let comp () = print_string "0 "; print_string (perform E); print_string "3 " main let main () = try comp () with effect E k -> print_string "1 "; continue k "2 "; pc print_string “4 " sp k 0 1 2 3
Compilation effect E : string let comp () = print_string "0 "; print_string (perform E); print_string "3 " main let main () = try comp () with effect E k -> print_string "1 "; continue k "2 "; print_string “4 " sp k pc 0 1 2 3 4
Handlers can be nested effect A : unit effect B : unit let baz () = pc perform A parent parent let bar () = try foo bar baz baz () with effect B k -> continue k () let foo () = try bar () sp with effect A k -> continue k ()
Handlers can be nested effect A : unit effect B : unit let baz () = perform A parent parent let bar () = try foo bar baz baz () with effect B k -> continue k () let foo () = try bar () sp with effect A k -> pc continue k ()
Handlers can be nested effect A : unit effect B : unit let baz () = perform A parent let bar () = try foo bar baz baz () with effect B k -> continue k () let foo () = try bar () sp with effect A k -> pc continue k () k
Handlers can be nested effect A : unit effect B : unit let baz () = perform A parent let bar () = try foo bar baz baz () with effect B k -> continue k () let foo () = try bar () sp with effect A k -> pc continue k () k • Linear search through handlers • Handler stacks shallow in practice
Deep-dive into perform
Deep-dive into perform • Full power of pattern matching for matching effects ✦ Tag test + branching is compiled to a function
Deep-dive into perform • Full power of pattern matching for matching effects ✦ Tag test + branching is compiled to a function https://github.com/ocaml-multicore/ocaml-multicore/blob/parallel_minor_gc/runtime/amd64.S#L865
Performance • Intel(R) Xeon(R) Gold 5120 CPU @ 2.20GHz ✦ For reference, memory read latency is 90 ns (local NUMA node) and 145 ns (remote NUMA node)
Recommend
More recommend