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

Affine Killing - TyDe'17

Kiko
September 03, 2017

Affine Killing - TyDe'17

Kiko

September 03, 2017
Tweet

More Decks by Kiko

Other Decks in Research

Transcript

  1. • Speculative, parallel abstractions: Problem • Easy to create parallelisation

    points • Hard to kill speculative computations (based on ParT)
  2. Problem { } { } (based on ParT) { _

    } :: t → Par[t] Types
  3. Problem { } { } (based on ParT) { _

    } :: t → Par[t] >> :: Par[t] → (t → t’)→ Par[t’] Types >> λ >> λ λ = (fun social => findUser(social, user))
  4. Problem { } { } parFb parTw (based on ParT)

    { _ } :: t → Par[t] >> :: Par[t] → (t → t’)→ Par[t’] Types >> λ >> λ λ = (fun social => findUser(social, user))
  5. Problem || { } { } parFb parTw (based on

    ParT) { _ } :: t → Par[t] || :: Par[t] → Par[t] → Par[t] >> :: Par[t] → (t → t’)→ Par[t’] Types >> λ >> λ λ = (fun social => findUser(social, user))
  6. Problem || phoneNumber << { } { } parFb parTw

    (based on ParT) { _ } :: t → Par[t] || :: Par[t] → Par[t] → Par[t] >> :: Par[t] → (t → t’)→ Par[t’] Types >> λ >> λ λ = (fun social => findUser(social, user)) ≪ :: (t → Par[t’]) → Par[t] → Par[t’]
  7. Problem >> updateDB || phoneNumber << { } { }

    parFb parTw (based on ParT) { _ } :: t → Par[t] || :: Par[t] → Par[t] → Par[t] >> :: Par[t] → (t → t’)→ Par[t’] Types >> λ >> λ λ = (fun social => findUser(social, user)) ≪ :: (t → Par[t’]) → Par[t] → Par[t’]
  8. Problem { } val parTw = >> (fun x =>

    findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) (based on ParT)
  9. Problem val parInf = parTw || parFb { } val

    parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) (based on ParT)
  10. Problem val parInf = parTw || parFb parTw >> updateDB

    { } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) (based on ParT)
  11. Problem getPhoneNumber ≪ parInf val parInf = parTw || parFb

    parTw >> updateDB { } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) (based on ParT)
  12. Problem getPhoneNumber ≪ parInf val parInf = parTw || parFb

    parTw >> updateDB { } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) (based on ParT) Aliasing prevents killing unfinished computations
  13. Problem getPhoneNumber ≪ parInf val parInf = parTw || parFb

    parTw >> updateDB { } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) (based on ParT) When is it safe to kill computations? How to do it efficiently? Aliasing prevents killing unfinished computations
  14. Solution 1. Kill using thread-local reasoning 2. Leverage static information

    from type system 3. No manual introduction of killing points 4. Integrated in the actor-based Encore language Limitation: Computations must be free of side effects
  15. Affine type system val parInf = parTw || parFb {

    } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) (parTw >> updateDB)
  16. Affine type system val parInf = parTw || parFb {

    } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) modes read ≊ shared lin ≊ affine fun findUser(social : lin Twitter, user : read User): read Info … end (parTw >> updateDB)
  17. Affine type system val parInf = parTw || parFb {

    } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) modes read ≊ shared lin ≊ affine fun findUser(social : lin Twitter, user : read User): read Info … end >> :: mode1 Par[mode2 t] → (mode2 t → mode2’ t’) → mode1’ Par[mode2’ t’] (parTw >> updateDB)
  18. Affine type system val parInf = parTw || parFb {

    } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) modes read ≊ shared lin ≊ affine fun findUser(social : lin Twitter, user : read User): read Info … end read Par[read Info] >> :: mode1 Par[mode2 t] → (mode2 t → mode2’ t’) → mode1’ Par[mode2’ t’] (parTw >> updateDB)
  19. Affine type system val parInf = parTw || parFb {

    } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) modes read ≊ shared lin ≊ affine fun findUser(social : lin Twitter, user : read User): read Info … end lin Par[read Info] read Par[read Info] >> :: mode1 Par[mode2 t] → (mode2 t → mode2’ t’) → mode1’ Par[mode2’ t’] (parTw >> updateDB)
  20. Affine type system val parInf = parTw || parFb {

    } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) modes read ≊ shared lin ≊ affine fun findUser(social : lin Twitter, user : read User): read Info … end lin Par[read Info] read Par[read Info] lin Par[read Info] >> :: mode1 Par[mode2 t] → (mode2 t → mode2’ t’) → mode1’ Par[mode2’ t’] (parTw >> updateDB)
  21. >> updateDB phoneNumber << parTw { }>> λ || parFb

    { }>> λ read linear Kill using thread-local reasoning
  22. >> updateDB phoneNumber << parTw { }>> λ || parFb

    { }>> λ read linear Kill using thread-local reasoning
  23. >> updateDB phoneNumber << parTw { }>> λ || parFb

    { }>> λ read linear Kill using thread-local reasoning parTw Information from Twitter available
  24. >> updateDB phoneNumber << parTw { }>> λ || read

    linear Kill using thread-local reasoning parTw Information from Twitter available
  25. >> updateDB phoneNumber << parTw { }>> λ || parFb

    { }>> λ read linear Kill using thread-local reasoning
  26. >> updateDB phoneNumber << parTw { }>> λ || parFb

    { }>> λ read linear Kill using thread-local reasoning parFb Information from Facebook available
  27. >> updateDB phoneNumber << parTw { }>> λ || parFb

    { }>> λ read linear Kill using thread-local reasoning parFb Information from Facebook available No operation
  28. >> updateDB λ << >> λ || read Kill using

    thread-local reasoning linear linear || linear >> λ linear { } { }
  29. >> updateDB λ << >> λ || read Kill using

    thread-local reasoning linear linear || linear >> λ linear { } { }
  30. >> updateDB λ << >> λ || read Kill using

    thread-local reasoning linear || linear { }
  31. || lin || lin v3 v4 || read v1 v2

    parInf= val parInf = parTw || parFb lin Par[read Info] || parInst || parReddit Leverage static information
  32. || lin || lin v3 v4 || read v1 v2

    parInf= statically checked val parInf = parTw || parFb lin Par[read Info] || parInst || parReddit Leverage static information
  33. || lin || lin v3 v4 || read v1 v2

    parInf= statically checked labels change at runtime val parInf = parTw || parFb lin Par[read Info] || parInst || parReddit Leverage static information
  34. || lin || lin v3 v4 || read v1 v2

    parInf= statically checked labels change at runtime val parInf = parTw || parFb lin Par[read Info] || parInst || parReddit Leverage static information Translates into: - Reuse of ParT collection structure - Polymorphic dispatch
  35. Leverage static information - Polymorphic dispatch ParT is statically checked,

    but the actual behaviour depends on the dynamic labels, which themselves may change
  36. Leverage static information - Polymorphic dispatch ParT is statically checked,

    but the actual behaviour depends on the dynamic labels, which themselves may change
  37. Leverage static information - Polymorphic dispatch ParT is statically checked,

    but the actual behaviour depends on the dynamic labels, which themselves may change
  38. || lin || lin v3 v4 || read v1 v2

    Sharing a linear reference parInf= parInf :: lin Par[read Info] Leverage static information
  39. || lin || lin v3 v4 || read v1 v2

    let !x = parInf in (!x >> λ) Sharing a linear reference parInf= parInf :: lin Par[read Info] Leverage static information
  40. || lin || lin v3 v4 || read v1 v2

    let !x = parInf in (!x >> λ) Sharing a linear reference parInf= parInf :: lin Par[read Info] !x :: read Par[read Info] !x = Leverage static information
  41. || lin || lin v3 v4 || read v1 v2

    let !x = parInf in (!x >> λ) Sharing a linear reference parInf= parInf :: lin Par[read Info] !x :: read Par[read Info] !x = read Leverage static information
  42. || lin || lin v3 v4 || read v1 v2

    let !x = parInf in (!x >> λ) Sharing a linear reference parInf= parInf :: lin Par[read Info] !x :: read Par[read Info] !x = read Leverage static information
  43. || lin || lin v3 v4 || read v1 v2

    let !x = parInf in (!x >> λ) Sharing a linear reference parInf= parInf :: lin Par[read Info] !x :: read Par[read Info] !x = read Leverage static information ParT is statically checked, but the actual behaviour depends on the dynamic labels, which themselves may change
  44. || lin || lin v3 v4 || read v1 v2

    let !x = parInf in (!x >> λ) Sharing a linear reference parInf= parInf :: lin Par[read Info] !x :: read Par[read Info] !x = read Leverage static information ParT is statically checked, but the actual behaviour depends on the dynamic labels, which themselves may change
  45. Integration with Encore • Actor-based language • Capability-based type system

    linear subord active local Cannot escape its actor read Immutable No aliasing allowed Cannot escape its aggregate Actor, method calls return futures Restriction: A type has a single capability type
  46. Integration with Encore • Actor-based language • Capability-based type system

    linear subord active local Cannot escape its actor read Immutable No aliasing allowed Cannot escape its aggregate Actor, method calls return futures Restriction: A type has a single capability type
  47. Integration with Encore • Actor-based language • Capability-based type system

    linear subord active local Cannot escape its actor read Immutable No aliasing allowed Cannot escape its aggregate Actor, method calls return futures Restriction: A type has a single capability type
  48. Integration with Encore • Actor-based language • Capability-based type system

    linear subord active local Cannot escape its actor read Immutable No aliasing allowed Cannot escape its aggregate Actor, method calls return futures Restriction: A type has a single capability type
  49. Work in progress • How to kill: • Proof of

    soundness • Implementation • Guided by SAT solver and other benchmarks - Kill thread, actor or introduce well-defined stopping points - ParT internally relies on a task or actor running computations
  50. Conclusion • Killing in an affine type system: • read

    (shared) references are nop • linear references can be killed • Thread-local reasoning when killing parallel computations • Leverage static information: e.g. polymorphic dispatch, in-place updates • Integration with Encore (status)