Kiko
September 03, 2017

# Affine Killing - TyDe'17

#### Kiko

September 03, 2017

## Transcript

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

points • Hard to kill speculative computations (based on ParT)

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 => ﬁndUser(social, user))
6. ### Problem { } { } parFb parTw (based on ParT)

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

ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) (based on ParT)
11. ### Problem val parInf = parTw || parFb { } val

parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) (based on ParT)
12. ### Problem val parInf = parTw || parFb parTw >> updateDB

{ } val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) (based on ParT)
13. ### Problem getPhoneNumber ≪ parInf val parInf = parTw || parFb

parTw >> updateDB { } val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) (based on ParT)
14. ### Problem getPhoneNumber ≪ parInf val parInf = parTw || parFb

parTw >> updateDB { } val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) (based on ParT) Aliasing prevents killing unﬁnished computations
15. ### Problem getPhoneNumber ≪ parInf val parInf = parTw || parFb

parTw >> updateDB { } val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) (based on ParT) When is it safe to kill computations? How to do it efﬁciently? Aliasing prevents killing unﬁnished 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

18. ### Afﬁne type system val parInf = parTw || parFb {

} val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) (parTw >> updateDB)
19. ### Afﬁne type system val parInf = parTw || parFb {

} val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) modes read ≊ shared lin ≊ afﬁne fun ﬁndUser(social : lin Twitter, user : read User): read Info … end (parTw >> updateDB)
20. ### Afﬁne type system val parInf = parTw || parFb {

} val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) modes read ≊ shared lin ≊ afﬁne fun ﬁndUser(social : lin Twitter, user : read User): read Info … end >> :: mode1 Par[mode2 t] → (mode2 t → mode2’ t’) → mode1’ Par[mode2’ t’] (parTw >> updateDB)
21. ### Afﬁne type system val parInf = parTw || parFb {

} val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) modes read ≊ shared lin ≊ afﬁne fun ﬁndUser(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. ### Afﬁne type system val parInf = parTw || parFb {

} val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) modes read ≊ shared lin ≊ afﬁne fun ﬁndUser(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. ### Afﬁne type system val parInf = parTw || parFb {

} val parTw = >> (fun x => ﬁndUser(social, user)) { } val parFb = >> (fun x => ﬁndUserFb(social, user)) modes read ≊ shared lin ≊ afﬁne fun ﬁndUser(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)

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-deﬁned stopping points - ParT internally relies on a task or actor running computations
55. ### Conclusion • Killing in an afﬁne 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)