Affine Killing - TyDe'17

2df7339e6f646abdc75d6fe1e954814a?s=47 Kiko
September 03, 2017

Affine Killing - TyDe'17

2df7339e6f646abdc75d6fe1e954814a?s=128

Kiko

September 03, 2017
Tweet

Transcript

  1. Affine Killing Kiko Fernandez-Reyes and Dave Clarke Uppsala University SCADA

    Funded by:
  2. • Speculative, parallel abstractions: Problem • Easy to create parallelisation

    points • Hard to kill speculative computations (based on ParT)
  3. Problem (based on ParT) Types

  4. Problem { } { } (based on ParT) { _

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

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

    { _ } :: t → Par[t] >> :: Par[t] → (t → t’)→ Par[t’] Types >> λ >> λ λ = (fun social => findUser(social, user))
  7. 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))
  8. 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’]
  9. 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’]
  10. Problem { } val parTw = >> (fun x =>

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

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

    { } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) (based on ParT)
  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)
  14. 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
  15. 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
  16. 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
  17. Outline • Problem • Affine type system • Solution

  18. Affine type system val parInf = parTw || parFb {

    } val parTw = >> (fun x => findUser(social, user)) { } val parFb = >> (fun x => findUserFb(social, user)) (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 (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 >> :: mode1 Par[mode2 t] → (mode2 t → mode2’ t’) → mode1’ Par[mode2’ t’] (parTw >> updateDB)
  21. 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)
  22. 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)
  23. 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)
  24. Outline • Problem • Affine type system • Solution

  25. >> updateDB phoneNumber << parTw { }>> λ || parFb

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

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

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

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

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

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

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

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

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

    thread-local reasoning linear || linear { }
  35. val parInf = parTw || parFb lin Par[read Info] Leverage

    static information
  36. || lin || lin v3 v4 || read v1 v2

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

    parInf= statically checked val parInf = parTw || parFb lin Par[read Info] || parInst || parReddit Leverage static information
  38. || 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
  39. || 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
  40. Leverage static information - Polymorphic dispatch ParT is statically checked,

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

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

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

    Sharing a linear reference parInf= parInf :: lin Par[read Info] Leverage static information
  44. || 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
  45. || 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
  46. || 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
  47. || 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
  48. || 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
  49. || 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
  50. 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
  51. 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
  52. 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
  53. 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
  54. 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
  55. 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)