reagents lock free programming for the masses
play

Reagents: lock-free programming for the masses KC Sivaramakrishnan - PowerPoint PPT Presentation

Reagents: lock-free programming for the masses KC Sivaramakrishnan University of OCaml Cambridge Labs Multicore OCaml Concurrency Parallelism Libraries Language + Stdlib Compiler 2 Multicore OCaml Concurrency Parallelism


  1. Reagents: lock-free programming for the masses “KC” Sivaramakrishnan University of OCaml Cambridge Labs

  2. Multicore OCaml Concurrency Parallelism Libraries Language + Stdlib Compiler 2

  3. Multicore OCaml Concurrency Parallelism Libraries Language + Stdlib Compiler 2

  4. Multicore OCaml Concurrency Parallelism Libraries Language + Stdlib Compiler Fibers 2

  5. Multicore OCaml Concurrency Parallelism Libraries Language + Stdlib Compiler • 12M fibers/s on 1 core Fibers • 30M fibers/s on 4 cores 2

  6. Multicore OCaml Concurrency Parallelism Libraries Language + Stdlib Compiler • 12M fibers/s on 1 core Fibers Domains • 30M fibers/s on 4 cores 2

  7. Multicore OCaml Concurrency Parallelism Libraries Language + Stdlib Effects Domain API Compiler • 12M fibers/s on 1 core Fibers Domains • 30M fibers/s on 4 cores 2

  8. Multicore OCaml Concurrency Parallelism Libraries Cooperative threading libraries Language + Stdlib Effects Domain API Compiler • 12M fibers/s on 1 core Fibers Domains • 30M fibers/s on 4 cores 2

  9. Multicore OCaml Concurrency Parallelism Libraries Cooperative Reagents : lock- threading libraries free programming Language + Stdlib Effects Domain API Compiler • 12M fibers/s on 1 core Fibers Domains • 30M fibers/s on 4 cores 2

  10. JVM: java.util.concurrent .Net: System.Concurrent.Collections 3

  11. JVM: java.util.concurrent .Net: System.Concurrent.Collections Synchronization Data structures Reentrant locks Queues Semaphores Nonblocking R/W locks Blocking (array & list) Reentrant R/W locks Synchronous Condition variables Priority, nonblocking Countdown latches Priority, blocking Cyclic barriers Deques Phasers Sets Exchangers Maps (hash & skiplist) 3

  12. JVM: java.util.concurrent .Net: System.Concurrent.Collections Synchronization Data structures Reentrant locks Queues Not Composable Semaphores Nonblocking R/W locks Blocking (array & list) Reentrant R/W locks Synchronous Condition variables Priority, nonblocking Countdown latches Priority, blocking Cyclic barriers Deques Phasers Sets Exchangers Maps (hash & skiplist) 3

  13. How to build composable lock-free programs? 4

  14. lock-free 5

  15. lock-free Under contention, at least 1 thread makes progress 5

  16. lock-free Under contention, at least 1 thread makes progress obstruction-free Single thread in isolation makes progress 5

  17. wait-free Under contention, each thread makes progress lock-free Under contention, at least 1 thread makes progress obstruction-free Single thread in isolation makes progress 5

  18. Compare-and-swap (CAS) module CAS : sig val cas : 'a ref -> expect:'a -> update:'a -> bool end = struct (* atomically... *) let cas r ~expect ~update = if !r = expect then (r:= update; true) else false end 6

  19. Compare-and-swap (CAS) module CAS : sig val cas : 'a ref -> expect:'a -> update:'a -> bool end = struct (* atomically... *) let cas r ~expect ~update = if !r = expect then (r:= update; true) else false end • Implemented atomically by processors • x86: CMPXCHG and friends • arm: LDREX, STREX, etc. • ppc: lwarx, stwcx, etc. 6

  20. Head 3 2 7

  21. Head 3 2 7 7

  22. Head 3 2 CAS attempt 7 7

  23. Head 5 3 2 CAS attempt 7 7

  24. Head 5 3 2 CAS fail 7 7

  25. Head 5 3 2 7 7

  26. Head 5 3 2 7 8

  27. module type TREIBER_STACK = sig type 'a t val push : 'a t -> 'a -> unit ... end module Treiber_stack : TREIBER_STACK = struct type 'a t = 'a list ref let rec push s t = let cur = !s in if CAS.cas s cur (t::cur) then () else (backoff (); push s t) end 9

  28. module type TREIBER_STACK = sig type 'a t val push : 'a t -> 'a -> unit val try_pop : 'a t -> 'a option end module Treiber_stack : TREIBER_STACK = struct type 'a t = 'a list ref let rec push s t = ... let rec try_pop s = match !s with | [] -> None | (x::xs) as cur -> if CAS.cas s cur xs then Some x else (backoff (); try_pop s) end 10

  29. let v = Treiber_stack.pop s1 in Treiber_stack.push s2 v is not atomic 11

  30. The Problem: Concurrency libraries are indispensable, but hard to build and extend let v = Treiber_stack.pop s1 in Treiber_stack.push s2 v is not atomic 11

  31. Reagents Scalable concurrent algorithms can be built and extended using abstraction and composition Treiber_stack.pop s1 >>> Treiber_stack.push s2 is atomic 12

  32. PLDI 2012 13

  33. PLDI 2012 Sequential >>> — Software transactional memory Parallel <*> — Join Calculus Selective <+> — Concurrent ML 13

  34. PLDI 2012 Sequential >>> — Software transactional memory Parallel <*> — Join Calculus Selective <+> — Concurrent ML still lock-free! 13

  35. Design 14

  36. Lambda: the ultimate abstraction 'a 'b 'b 'c f g val f : 'a -> 'b val g : 'b -> 'c 15

  37. Lambda: the ultimate abstraction 'a 'b 'c f g (compose g f): 'a -> 'c 16

  38. 'a 'b Lambda abstraction: f 17

  39. 'a 'b Lambda abstraction: f 'a 'b Reagent abstraction: R ('a,'b) Reagent.t 17

  40. 'a 'b Lambda abstraction: f 'a 'b Reagent abstraction: R ('a,'b) Reagent.t val run : ('a,'b) Reagent.t -> 'a -> ‘b 17

  41. Thread Interaction module type Reagents = sig type ('a,'b) t (* shared memory *) module Ref : Ref.S with type ('a,'b) reagent = ('a,'b) t (* communication channels *) module Channel : Channel.S with type ('a,'b) reagent = ('a,'b) t ... end 18

  42. module type Channel = sig type ('a,'b) endpoint type ('a,'b) reagent val mk_chan : unit -> ('a,'b) endpoint * ('b,'a) endpoint val swap : ('a,'b) endpoint -> ('a,'b) reagent end

  43. module type Channel = sig type ('a,'b) endpoint type ('a,'b) reagent val mk_chan : unit -> ('a,'b) endpoint * ('b,'a) endpoint val swap : ('a,'b) endpoint -> ('a,'b) reagent end c : ('a,'b) endpoint 'a 'b swap c

  44. module type Channel = sig type ('a,'b) endpoint type ('a,'b) reagent val mk_chan : unit -> ('a,'b) endpoint * ('b,'a) endpoint val swap : ('a,'b) endpoint -> ('a,'b) reagent end c : ('a,'b) endpoint 'a 'b swap c c swap 'b 'a

  45. c : ('a,'b) endpoint 'b 'a swap c

  46. type 'a ref val upd : 'a ref Message passing -> f:(‘a -> 'b -> ('a * ‘c) option) -> ('b, 'c) Reagent.t swap 21

  47. type 'a ref val upd : 'a ref Message passing -> f:(‘a -> 'b -> ('a * ‘c) option) -> ('b, 'c) Reagent.t upd 'b 'c swap f r 'a 'a 21

  48. Message passing Shared state upd swap f 22

  49. Message passing Shared state upd swap f 'a 'b R 'a 'b S 22

  50. Message passing Shared state upd swap f R 'a 'b <+> S 22

  51. Message passing Shared state upd swap f Disjunction R <+> S 23

  52. Message passing Shared state upd swap f Disjunction 'a 'b R R <+> 'a 'c S S 23

  53. Message passing Shared state upd swap f Disjunction R R ' a ('b * 'c) <+> <*> S S 23

  54. Message passing Shared state upd swap f Conjunction Disjunction R R <+> <*> S S 24

  55. module type TREIBER_STACK = sig type 'a t val create : unit -> 'a t val push : 'a t -> ('a, unit) Reagent.t val pop : 'a t -> (unit, 'a) Reagent.t ... end module Treiber_stack : TREIBER_STACK = struct type 'a t = 'a list Ref.ref let create () = Ref.ref [] let push r x = Ref.upd r (fun xs x -> Some (x::xs,())) let pop r = Ref.upd r (fun l () -> match l with | [] -> None (* block *) | x::xs -> Some (xs,x)) ... end 25

  56. Composability Transfer elements atomically Treiber_stack.pop s1 >>> Treiber_stack.push s2 26

  57. Composability Transfer elements atomically Treiber_stack.pop s1 >>> Treiber_stack.push s2 Consume elements atomically Treiber_stack.pop s1 <*> Treiber_stack.pop s2 26

  58. Composability Transfer elements atomically Treiber_stack.pop s1 >>> Treiber_stack.push s2 Consume elements atomically Treiber_stack.pop s1 <*> Treiber_stack.pop s2 Consume elements from either Treiber_stack.pop s1 <+> Treiber_stack.pop s2 26

  59. Composability Transform arbitrary blocking reagent to a non-blocking reagent 27

  60. Composability Transform arbitrary blocking reagent to a non-blocking reagent val lift : ('a -> 'b option) -> ('a,'b) t val constant : 'a -> ('b,'a) t 27

  61. Composability Transform arbitrary blocking reagent to a non-blocking reagent val lift : ('a -> 'b option) -> ('a,'b) t val constant : 'a -> ('b,'a) t let attempt (r : ('a,'b) t) : ('a,'b option) t = (r >>> lift (fun x -> Some (Some x))) <+> (constant None) 27

  62. Composability Transform arbitrary blocking reagent to a non-blocking reagent val lift : ('a -> 'b option) -> ('a,'b) t val constant : 'a -> ('b,'a) t let attempt (r : ('a,'b) t) : ('a,'b option) t = (r >>> lift (fun x -> Some (Some x))) <+> (constant None) let try_pop stack = attempt (pop stack) 27

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend