1 / 30

Tim Sheard Oregon Graduate Institute

Fundamentals of. Staged Computation. Tim Sheard Oregon Graduate Institute. Lecture 3: More Examples. CSE 510 Section FSC Winter 2004. Assignments. The paper DSL Implementation Using Staging and Monads is now officially assigned. See the web page to obtain a copy.

makoto
Download Presentation

Tim Sheard Oregon Graduate Institute

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Fundamentals of Staged Computation Tim Sheard Oregon Graduate Institute Lecture 3: More Examples CSE 510 Section FSC Winter 2004

  2. Assignments • The paper DSL Implementation Using Staging and Monads is now officially assigned. See the web page to obtain a copy. • A volunteer presenter is needed to present the paper next Monday. • Homework 2, due in one week, is now assigned. See webpage for details • Due in one week, Monday Jan 18 Cse583 Winterl 2002

  3. An Interesting Note • Some functions are code transformers • plus : int -> <int> -> <int> • plus x ycode = < ~(lift x) + ~ycode > • Others are code generators • plus' : int -> <int -> int> • plus' x = <fn y => ~(lift x) + y> • When do we use one? When do we use the other? Are they equivalent? Cse583 Winterl 2002

  4. Transformers to generators • Code transformers can be made code generators with a “trick” fun plus’’ n = <fn y => ~(plus n <y>)>; -| plus’’ 3; val it = <(fn a = 3 %+ a)> : <int -> int> Cse583 Winterl 2002

  5. Another example: two versions fun add3 0 y = y | add3 n y = < 1 + ~(add3 (n-1) y)>; fun add4 0 = <fn y => y> | add4 n = <fn y => 1 + ~(add4 (n-1)) y>; Cse583 Winterl 2002

  6. Exponentially large generated programs fun even x = (x mod 2) = 0; fun filter p [] = <[]> | filter p (x::xs) = <if ~p ~(lift x) then ~(filter p xs) else ~(lift x) :: ~(filter p xs)>; -| filter <even> [3]; val it = <if %even 3 then [] else [3]> : <int list> Note the repeated, related (here identical) , recursive calls Cse583 Winterl 2002

  7. But let the list grow -| filter <even> [1,2,3,4]; val it = <if %even 1 then if %even 2 then if %even 3 then if %even 4 then [] else [4] else 3 :: if %even 4 then [] else [4] else 2 :: if %even 3 then if %even 4 then [] else [4] else 3 :: if %even 4 then [] else [4] else 1 :: if %even 2 then if %even 3 then if %even 4 then [] else [4] else 3 :: if %even 4 then [] else [4] else 2 :: if %even 3 then if %even 4 then [] else [4] else 3 :: if %even 4 then [] else [4]> : <int list> Cse583 Winterl 2002

  8. Use let to share calls fun filter p [] = <[]> | filter p (x::xs) = <let val ys = ~(filter p xs) in if ~p ~(lift x) then ys else ~(lift x) :: ys end>; val ex2 = filter <even> [1,2,3,4]; -| val ex2 = <let val a = [] val b = if %even 4 then a else 4 :: a val c = if %even 3 then b else 3 :: b val d = if %even 2 then c else 2 :: c in if %even 1 then d else 1 :: d end> Cse583 Winterl 2002

  9. Staged Shortest Path • Given a directed weighted graph G=(V,E) • Two nodes a,b in V, • The shortest path algorithm finds the minimum weighted path in G from the source a to the destination b. • Where the weights are given by a weight function W Cse583 Winterl 2002

  10. 3 5 2 1 4 Representing Graphs fun g x = case x of 1 => [2] | 2 => [3,4] | 3 => [5] | 4 => [1,2,5] | 5 => [4] | _ => []; Cse583 Winterl 2002

  11. Structure of function • fun shortestPath succ source dest marked weight = . . . • succ is the function associating to a vertex a list of successor vertexes, and encodes the topology of the graph • source is the source vertex; • dest is the destination vertex; • marked indicates which nodes have already been visited by the algorithm; • (weight x y) indicates the weight of the edge (x,y). Cse583 Winterl 2002

  12. Helper functions (* min : int -> int -> int *) fun min x z = if x '<' z then x else z ; (* minimum : int list -> int *) fun minimum (x::xs) = (case xs of [] => x | _ => min x (minimum xs)); (* map : ('b -> 'a) -> 'b list -> 'a list *) fun map f [] = [] | map f (a::b) = (f a)::(map f b); (* mem : int -> int list -> bool *) fun mem x [] = false | mem x (a::b) = if a=x then true else mem x b; (* minus : int list -> int list -> int list *) fun minus [] ys = [] | minus (a::b) ys = if mem a ys then minus b ys else a::(minus b ys); Cse583 Winterl 2002

  13. shortestPath fun shortestPath succ source dest marked weight = if source = dest then 0 else let val marked2 = (source::marked) val explore = (minus (succ source) marked2) fun short x = shortestPath succ x dest marked2 weight val path_weights = map (fn node => (short node) + (weight source node)) explore in case path_weights of [] => infinity | _ => (minimum path_weights) end; Cse583 Winterl 2002

  14. 3 5 2 1 4 Example • val ex1 = let fun weight x y = 1 in shortestPath g 3 2 [] weight end; -| val ex1 = 3 : int Cse583 Winterl 2002

  15. Staging shortestPath • The graph is known • The source and destination are known • The weight function is dynamic and won’t be known until later. shortestPath : graph -> int -> int -> int list -> (int -> int -> int) -> int shortestPath2 : graph -> int -> int -> int list -> <(int -> int -> int) -> int> Cse583 Winterl 2002

  16. Stage helper functions • Staging the minimum function liftMinimum : <int> list -> <int> fun liftMinimum x = case x of [] => <infinity> | (c::cs) => <min ~c ~(liftMinimum cs)>; Cse583 Winterl 2002

  17. shortestPath2 fun shortestPath2 succ source dest marked = <fn weight => ~(if source = dest then <0> else let val marked2 = source::marked val explore = (minus (succ source) marked) fun short x = shortestPath2 succ x dest marked2 val path_weights = map (fn node => < (~(short node) weight) + (weight ~(lift source) ~(lift node)) > ) explore in (liftMinimum path_weights) end ) >; Note shortestPath2 is in generator style Cse583 Winterl 2002

  18. 3 5 2 1 4 Results -| val ex2 = (shortestPath2 g 4 2 []); val ex2 = <(fn a => %min (%min (0 %+ a 1 2) (%infinity %+ a 4 1)) (%min (0 %+ a 4 2) (%min (%infinity %+ a 4 5) %infinity)))> : <(int -> int -> int) -> int> Cse583 Winterl 2002

  19. Unnest the calls to min fun liftMinimum x = case x of [] => <infinity> | [x] => x | ( <infinity> :: cs) => liftMinimum cs | (c::cs) => <let val y = ~(liftMinimum cs) val z = ~c in min z y end>; Note special case for singleton list Cse583 Winterl 2002

  20. shortestPath2 again fun shortestPath2 succ source dest marked = <fn weight => ~(if source = dest then <0> else let val marked2 = source::marked val explore = (minus (succ source) marked) fun short x = shortestPath2 succ x dest marked2 val path_weights = map (fn node => let val recall = < ~(short node) weight> val wght = <weight ~(lift source) ~(lift node)> in <let val q = ~recall in q + ~wght end> end) explore in (liftMinimum path_weights) end ) >; Note the generated let Cse583 Winterl 2002

  21. 3 5 2 1 4 Results val ex2 = (shortestPath2 g 4 2 []); -| val ex2 = <(fn a => let val b = %infinity %+ a 4 5 val c = 0 %+ a 4 2 val d = %min c b val e = 0 %+ a 1 2 val f = e %+ a 4 1 in %min f d end)> : <(int -> int -> int) -> int> Cse583 Winterl 2002

  22. Extended example 2 • Staged merge function for sorted lists • Un-staged version fun merge xs ys = case xs of [] => ys | (z::zs) => case ys of [] => xs | w::ws => if z '<' (w:int) then z::(merge zs ys) else w::(merge xs ws); Suppose xs is static and ys is dynamic Cse583 Winterl 2002

  23. First staged attempt fun merge2 xs = <fn ys => ~(case xs of [] => <ys> | (z::zs) => <case ys of [] => ~(lift xs) | (w::ws) => if z '<' (w:int) then z::(~(merge2 zs) ys) else w::(~(merge2 xs) ws) >)>; Goes into an infinite loop. Why? Cse583 Winterl 2002

  24. Second Attempt • First some helper functions fun reverse [] ys = ys | reverse (x::xs) ys = (reverse xs (x::ys)); fun split2 (n:int) xs (small,big) = case xs of [] => (reverse small [], reverse big []) | (z::zs) => if z '>' n then split2 n zs (small,z::big) else split2 n zs (z::small,big); fun split n l = (split2 n l ([],[])); Cse583 Winterl 2002

  25. Unstaged version using the helper functions fun merge3 xs ys = case xs of [] => ys | z::zs => (case ys of [] => xs | w::ws => if z '<' w then z::(merge3 zs ys) else let val (u,v) = split z ys in append u (z::(merge3 zs v)) end ); u is all elements of ys less than z split avoids recursive call on xs Cse583 Winterl 2002

  26. Staged Version fun merge4 xs = <fn ys => ~(case xs of [] => <ys> | (b::bs) => <case ys of [] => ~(lift xs) | (w::ws) => if (~(lift b)) '<' w then (~(lift b))::(~(merge4 bs) ys) else let val (low,high) = split (~(lift b)) ys in append low (~(lift b)::(~(merge4 bs) high)) end >) >; Cse583 Winterl 2002

  27. Not so-good, Generated code -| merge4 [2,5]; val it = <(fn a => (case a of [] => [2,5] | (c::b) => if 2 %'<' c then 2 :: (case a of [] => [5] | (k::j) => if 5 %'<' k then 5 :: a else let val (m,l) = %split 5 a in %append m (5 :: l) end) else let val (e,d) = %split 2 a in %append e (2 :: (case d of [] => [5] | (g::f) => if 5 %'<' g then 5 :: d else let val (i,h) = %split 5 d in %append i (5 :: h) end)) end))> : <int list -> int list> Cse583 Winterl 2002

  28. Improve by • use transformer style • use let to share recursive call fun merge5 xs ys = case xs of [] => ys | (b::bs) => <case ~ys of [] => ~(lift xs) | (w::ws) => let val tail = ~(merge5 bs ys) val (low,high) = split (~(lift b)) ~ys in if (~(lift b)) '<' w then (~(lift b)):: tail else append low (~(lift b):: tail) end >; fun f1 xs = <fn ys => ~(merge5 xs <ys>)>; Cse583 Winterl 2002

  29. Better code -| f1 [2,3]; val it = <(fn a => (case a of [] => [2,3] | (c::b) => let val d = case a of [] => [3] | (f::e) => let val (h,g) = %split 3 a in if 3 %'<' f then 3 :: a else %append h (3 :: a) end) val (j,i) = %split 2 a in if 2 %'<' c then 2 :: d else %append j (2 :: d) end))> Cse583 Winterl 2002

  30. Review • Multiple stage programs require nested brackets. Transformer style is often useful. • Staged helper functions are often necessary. • Generated programs must follow all paths of a generated if or case, even if the unstaged version will follow only one path. • Leads to possiblility of exponentially growing code. • Can cause the generator not to terminate if recursive call at first level doesn’t “get smaller”, even though it gets smaller (in the second stage) in the unstaged program. • Use let to share similar or related code to avoid this blowup. • Use let to avoid deeply nested function calls. Simplifies the structure, and won’t blow up the object level compiler by generating code in weird ways. Cse583 Winterl 2002

More Related