Upgrade to Pro — share decks privately, control downloads, hide ads and more …

COORDINATION 2018

Kiko
June 20, 2018

COORDINATION 2018

Kiko

June 20, 2018
Tweet

More Decks by Kiko

Other Decks in Education

Transcript

  1. Forward to a Promising Future Kiko Fernandez-Reyes, Dave Clarke, Elias

    Castegren and Huu Phuc-Vo Uppsala University, Sweden
  2. Active object B Active object A Concurrent & Parallel Programming

    • Active Objects have existed since mid-80 s = future Abbreviation: active object = actor
  3. Active object B Active object A Concurrent & Parallel Programming

    • Active Objects have existed since mid-80 s = future Abbreviation: active object = actor
  4. Active object B Active object A Concurrent & Parallel Programming

    • Active Objects have existed since mid-80 s Value = future Abbreviation: active object = actor
  5. Active object B Active object A Concurrent & Parallel Programming

    • Active Objects have existed since mid-80 s = future Abbreviation: active object = actor
  6. Motivation Many computations block on a future to get its

    result only to return that result immediately
  7. Motivation Many computations block on a future to get its

    result only to return that result immediately
  8. Motivation Many computations block on a future to get its

    result only to return that result immediately
  9. Motivation Many computations block on a future to get its

    result only to return that result immediately
  10. 1. get 2. await Motivation Many computations block on a

    future to get its result only to return that result immediately
  11. 1. get 2. await Motivation Many computations block on a

    future to get its result only to return that result immediately
  12. 1. get 2. await Motivation Many computations block on a

    future to get its result only to return that result immediately
  13. 1. get 2. await Motivation Many computations block on a

    future to get its result only to return that result immediately Interesting for behavioural design patterns:
  14. 1. get 2. await Motivation Many computations block on a

    future to get its result only to return that result immediately Interesting for behavioural design patterns: Broker Mediator Chain of responsibility PubSub
  15. Broker Requesters broker!run( ) new Job(1) active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) return get(future) end end 2 1 Problem GET Responders
  16. Broker Requesters broker!run( ) new Job(1) active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) return get(future) end end 2 1 Problem GET Responders
  17. Broker Requesters broker!run( ) new Job(1) active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) return get(future) end end 2 1 Problem GET 1 Responders
  18. Broker Requesters broker!run( ) new Job(1) active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) return get(future) end end 2 1 Problem GET 1 Responders
  19. Broker Requesters broker!run( ) new Job(1) active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) return get(future) end end 2 1 Problem GET 1 2 Responders
  20. Broker Requesters broker!run( ) new Job(1) active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) return get(future) end end 2 1 Problem GET Value 1 2 Responders
  21. Broker Requesters broker!run( ) new Job(1) active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) return get(future) end end 2 1 Problem GET 1 2 Responders
  22. Broker Requesters broker!run( ) new Job(1) active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) return get(future) end end 2 1 Problem GET 1 2 Responders
  23. Broker Requesters broker!run( ) new Job(1) active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) return get(future) end end 2 1 Problem GET 1 2 Responders
  24. Broker Requesters broker!run( ) new Job(1) Problem Nothing active class

    Broker val workers: Buffered[Worker] var current: uint def run(job: Job): Fut int val worker = this.workers[++this.current % workers.size()] return worker!start(job) end end 1 Responders
  25. Broker Requesters broker!run( ) new Job(1) Problem Nothing active class

    Broker val workers: Buffered[Worker] var current: uint def run(job: Job): Fut int val worker = this.workers[++this.current % workers.size()] return worker!start(job) end end 1 Responders
  26. Broker Requesters broker!run( ) new Job(1) Problem Nothing active class

    Broker val workers: Buffered[Worker] var current: uint def run(job: Job): Fut int val worker = this.workers[++this.current % workers.size()] return worker!start(job) end end 1 Responders
  27. Broker Requesters broker!run( ) new Job(1) Problem Nothing active class

    Broker val workers: Buffered[Worker] var current: uint def run(job: Job): Fut int val worker = this.workers[++this.current % workers.size()] return worker!start(job) end end 1 Responders
  28. Broker Requesters broker!run( ) new Job(1) Problem Nothing active class

    Broker val workers: Buffered[Worker] var current: uint def run(job: Job): Fut int val worker = this.workers[++this.current % workers.size()] return worker!start(job) end end 1 Responders 1
  29. Broker Requesters broker!run( ) new Job(1) Problem Nothing active class

    Broker val workers: Buffered[Worker] var current: uint def run(job: Job): Fut int val worker = this.workers[++this.current % workers.size()] return worker!start(job) end end 1 Responders 1
  30. Broker Requesters broker!run( ) new Job(1) Problem AWAIT active class

    Broker val workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) await(future) return get(future) end end 2 1 Responders
  31. Broker Requesters broker!run(new Job(1),p) Problem Promise active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job, prom: Promise[int]): unit val worker = this.workers[++this.current % workers.size()] worker!start(job, prom) end end 3 Responders let p = new Prom() 1 2
  32. Broker Requesters broker!run(new Job(1),p) Problem Promise active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job, prom: Promise[int]): unit val worker = this.workers[++this.current % workers.size()] worker!start(job, prom) end end 3 Responders let p = new Prom() 1 1 2
  33. Broker Requesters broker!run(new Job(1),p) Problem Promise active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job, prom: Promise[int]): unit val worker = this.workers[++this.current % workers.size()] worker!start(job, prom) end end 3 Responders let p = new Prom() 1 1 2 2
  34. Broker Requesters broker!run(new Job(1),p) Problem Promise active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job, prom: Promise[int]): unit val worker = this.workers[++this.current % workers.size()] worker!start(job, prom) end end 3 Responders let p = new Prom() 1 1 2 2
  35. Broker Requesters broker!run(new Job(1),p) Problem Promise active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job, prom: Promise[int]): unit val worker = this.workers[++this.current % workers.size()] worker!start(job, prom) end end 3 Responders let p = new Prom() 1 1 2 2 3
  36. Broker Requesters broker!run(new Job(1),p) Problem Promise active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job, prom: Promise[int]): unit val worker = this.workers[++this.current % workers.size()] worker!start(job, prom) end end 3 Responders let p = new Prom() 1 1 2 2 3
  37. Broker Requesters broker!run(new Job(1),p) Problem Promise active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job, prom: Promise[int]): unit val worker = this.workers[++this.current % workers.size()] worker!start(job, prom) end end 3 Responders let p = new Prom() 1 1 2 2 3
  38. Broker Requesters broker!run(new Job(1),p) Problem Promise active class Broker val

    workers: Buffered[Worker] var current: uint def run(job: Job, prom: Promise[int]): unit val worker = this.workers[++this.current % workers.size()] worker!start(job, prom) end end 3 Responders let p = new Prom() 1 1 2 2 Value Value 3
  39. Broker Requesters broker.run( ) new Job(1) Explore Forward Broker broker!run(

    ) new Job(1) active class Broker val workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) forward(future) end end 1 Responders
  40. Broker Requesters broker.run( ) new Job(1) Explore Forward Broker broker!run(

    ) new Job(1) active class Broker val workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) forward(future) end end 1 Responders
  41. Broker Requesters broker.run( ) new Job(1) Explore Forward Broker broker!run(

    ) new Job(1) active class Broker val workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) forward(future) end end 1 Responders
  42. Broker Requesters broker.run( ) new Job(1) Explore Forward Broker broker!run(

    ) new Job(1) 1 active class Broker val workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) forward(future) end end 1 Responders
  43. Broker Requesters broker.run( ) new Job(1) Explore Forward Broker broker!run(

    ) new Job(1) 1 active class Broker val workers: Buffered[Worker] var current: uint def run(job: Job): int val worker = this.workers[++this.current % workers.size()] val future : Fut[int] = worker!start(job) forward(future) end end 1 Responders
  44. Requesters broker.run( ) new Job(1) Explore Forward Broker broker!run( )

    new Job(1) Value Responders forward(x!run(..)) forward(y!run(..)) forward(z!run(..))
  45. Requesters broker.run( ) new Job(1) Explore Forward Broker broker!run( )

    new Job(1) Value Responders forward(x!run(..)) forward(y!run(..)) forward(z!run(..))
  46. Contributions • High-level (future) task-based language • Low-level promise-based language

    • Compilation strategy from high- to low-level language (proof that translation is semantics preserving) • Implementation and microbenchmarks The formalisation captures the essence of the implementation
  47. Typing rules return type of a task • forbids the

    use of forward in contexts where the expected task type is not clear closure can be passed between tasks and run in a context different from their defining contexts
  48. Compilation Strategy Compilation of: • configurations • expressions and values

    • types e =future Bisimulation up-to expansion to proof that it is semantics preserving
  49. Implementation • Encore actor-based language • Compiled from Encore to

    C • Microbenchmarks Broker pattern: • get • await + get • forward
  50. (lower is better) Benchmark Memory Saves the whole stack on

    each context switch Creates more futures than the forwarding version Why?
  51. More goodies in paper Standard reduction rules Optimised reduction rules

    In-depth explanation of bisimulation using a LTS More examples of: • Reduction rules • Compilation strategy • etc
  52. Conclusion Main idea • Forward fixes: • get-and-return and •

    await-get-return Write high-level future-based code & Output low-level promise-based code with static fulfilment guarantees