effective parallelism with reagents
play

Effective Parallelism with Reagents KC Sivaramakrishnan University - PowerPoint PPT Presentation

Effective Parallelism with Reagents KC Sivaramakrishnan University of OCaml Cambridge Labs Multicore OCaml Concurrency Parallelism Libraries Language + Stdlib Compiler 2 Multicore OCaml Concurrency Parallelism Libraries


  1. 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 17

  2. let v = Treiber_stack.pop s1 in Treiber_stack.push s2 v is not atomic 18

  3. 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 18

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

  5. PLDI 2012 20

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

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

  8. Design 21

  9. Lambda: the ultimate abstraction 'a 'b 'b 'c f g val f : 'a -> 'b val g : 'b -> 'c 22

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

  11. 'a 'b Lambda abstraction: f 24

  12. 'a 'b Lambda abstraction: f 'a 'b Reagent abstraction: R ('a,'b) Reagent.t 24

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

  14. 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 25

  15. 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

  16. 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

  17. 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

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

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

  20. 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 28

  21. Message passing Shared state upd swap f 29

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

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

  24. Message passing Shared state upd swap f Disjunction R <+> S 30

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

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

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

  28. 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 32

  29. Composability Transfer elements atomically Treiber_stack.pop s1 >>> Treiber_stack.push s2 33

  30. Composability Transfer elements atomically Treiber_stack.pop s1 >>> Treiber_stack.push s2 Consume elements atomically Treiber_stack.pop s1 <*> Treiber_stack.pop s2 33

  31. 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 33

  32. Composability Transform arbitrary blocking reagent to a non-blocking reagent 34

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

  34. 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) 34

  35. 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) 34

  36. Philosopher’s alternate between thinking and • eating Philosopher can only eat after obtaining both • forks No philosopher starves •

  37. Philosopher’s alternate between thinking and • eating Philosopher can only eat after obtaining both • forks No philosopher starves • type fork = {drop : (unit,unit) endpoint; take : (unit,unit) endpoint} let mk_fork () = let drop, take = mk_chan () in {drop; take} let drop f = swap f.drop let take f = swap f.take

  38. Philosopher’s alternate between thinking and • eating Philosopher can only eat after obtaining both • forks No philosopher starves • type fork = {drop : (unit,unit) endpoint; let eat l_fork r_fork = take : (unit,unit) endpoint} run (take l_fork <*> take r_fork) (); let mk_fork () = (* ... let drop, take = mk_chan () in * eat * ... *) {drop; take} spawn @@ run (drop l_fork); spawn @@ run (drop r_fork) let drop f = swap f.drop let take f = swap f.take

  39. Implementation 36

  40. Phase 1 Phase 2 37

  41. Phase 1 Phase 2 Accumulate CASes 37

  42. Phase 1 Phase 2 Accumulate CASes Attempt k-CAS 37

  43. Accumulate CASes Attempt k-CAS 38

  44. Permanent failure Accumulate CASes Attempt k-CAS 38

  45. Permanent failure Transient failure Accumulate CASes Attempt k-CAS 38

  46. HTM Ready Permanent failure Transient failure Accumulate CASes Attempt k-CAS 38

  47. HTM Ready Permanent failure Transient failure Accumulate CASes Attempt k-CAS Promising early results with Intel TSX! 38

  48. X

  49. Permanent failure X

  50. Permanent failure Transient failure X

Recommend


More recommend