October 22
Same great algorithms,
awesome new hardware flavor
Hardware adaptation uses standard transformations:
The hard part is picking where to apply the transformations and selecting values for the transformation's parameters
Key Insights:
Automate the search!
What do we need?
A collection of rules that assign a property called a type to the parts of a computer program: variables, expressions, etc...
A typesystem allows you to:
A type
(τ:=D|[τ]|<τ,τ>|τ→τ)
A set of inference rules
(e:τ[e]:[τ])
These example types are part of the monad algebra
Type | Meaning |
---|---|
D | Primitive Type (int, float, etc...) |
[τ] | An array of elements with type τ |
<τ1,τ2> | A pair of elements of types τ1 and τ2. |
τ1→τ2 | A function with one argument of type τ1 and one return value of type τ2. |
Defined over a language of expressions like f(a,b).
a:τab:τbf(a,b):τf(τa,τb)If expression a has type τa and expression b has type τb...
...then expression f(a,b) has type τf(τa,τb).
A primitive language for describing data processing.
Operator | Meaning |
---|---|
λx.e | Define a function with body e that uses variable x. |
e1e2 | Apply the function defined by e1 to the value obtained from e2. |
ifcthene1elsee2 | If c is true then evaluate e1, and otherwise evaluate e2. |
Operator | Meaning |
---|---|
<e1,e2> | Construct a tuple from e1 and e2. |
e.i | Extract attribute i from the tuple e. |
[e] | Construct a single-element array from e. |
[] | Construct an empty array. |
e1⊔e2 | Concatenate the arrays e1 and e2. |
Apply function f to every element of array e. Concatenate all of the arrays returned by f.
foldL(c:τ2,f:<τ2,τ1>)(e:[τ1])Apply function f to every element of array e, with each invocation passing its return value to the next call (e.g., aggregation)
for(xB:[τ1][k]←ein:[τ1])(eloop:[τ2])
Extract blocks of size k from ein. For each block compute a flatMap using expression eloop.
Fold implements aggregation
Fold takes a 'previous' a and a 'current' x
We need a sum, and a count
Initial sum and count are both 0
Postprocess with division (λ creates a variable tot)
We need...
Basic Approach: Define a second type for tracking data sizes
α:=[α]x|<α1,α2>|ce.g., [<1,[1]y>]x corresponds to:
R(Γ,e) computes the cardinality type for e
Γ:x→α is a context / scope
cardinality(R(Γ,e1))k⋅ R(Γ′,e2)
The cardinality is based on that of e2
Repeated once for every time through the loop
And e2 is evaluated in the context of a k element array.
max(R(Γ,e1),R(Γ,e2))
Pessimistic assumption of biggest possible size.
Avoids needing to estimate p(c=true).
Expression | Context | Result Size |
---|---|---|
for(xB[k1]←R) | Γ1=R↦[1]x,S↦[1]y | [<1,1>]xk1⋅yk2⋅k1⋅k2 |
for(yB[k2]←S) | Γ2=Γ1∪xB↦[1]k1 | [<1,1>]yk2⋅k1⋅k2 |
for(x←xB) | Γ3=Γ2∪yB↦[1]k2 | [<1,1>]k1⋅k2 |
for(y←yB) | Γ4=Γ3∪x↦1 | [<1,1>]k2 |
ifjoinCond(x,y) | Γ5=Γ4∪y↦1 | [<1,1>]1 |
then[<x,y>] | Γ5 | [<1,1>]1 |
else[] | Γ5 | 0 |
IO Costs have 2 components:
Costs are defined for every pair of memory hierarchy levels:
Expression | Result Size | HDD to RAM | RAM to HDD |
---|---|---|---|
for(xB[k1]←R) | [<1,1>]xk1⋅yk2⋅k1⋅k2 | x+xk1y | 2xy |
for(yB[k2]←S) | [<1,1>]yk2⋅k1⋅k2 | y | 2k1y |
for(x←xB) | [<1,1>]k1⋅k2 | 0 | 2k1k2 |
for(y←yB) | [<1,1>]k2 | 0 | (1+1)k2 |
ifjoinCond(x,y) | [<1,1>]1 | 0 | (1+1)k2 |
then[<x,y>] | [<1,1>]1 | 0 | (1+1)k2 |
else[] | 0 | 0 | 0 |
HDD: R,S,Result RAM: x,xB,y,yB