generating efficient code
Download
Skip this Video
Download Presentation
Generating Efficient code

Loading in 2 Seconds...

play fullscreen
1 / 40

Generating Efficient code - PowerPoint PPT Presentation


  • 99 Views
  • Uploaded on

Generating Efficient code. Lecture 9. Assignment. Homework #6 is now available on the class web-site. Due next Tuesday, Feb 15, 2005 Read the paper ML Like Inference for Classifiers Assigned Thursday Feb 10, 2005 To be discussed, Thursday Feb 17, 2005 We will need a presenter ….

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Generating Efficient code' - alice


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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
assignment
Assignment
  • Homework #6 is now available on the class web-site.
    • Due next Tuesday, Feb 15, 2005
  • Read the paper
    • ML Like Inference for Classifiers
    • Assigned Thursday Feb 10, 2005
    • To be discussed, Thursday Feb 17, 2005
    • We will need a presenter …
generating efficient code1
Generating Efficient Code
  • Staged programs use known information to specialize complex algorithms.
  • This often introduces constants and code duplication.
  • Removing these inefficiencies after the fact is often difficult (if not impossible if code is abstract and cannot be taken apart).
  • Good tools can help us remove the efficiencies as we generate the code.
the region language
The region language

datatype Region

= Univ

| Empty

| Circle of real

| Rect of real * real

| Union of Region*Region

| Inter of Region*Region

| Trans of ((real*real)*Region);

example
Example

val c = Circle 1.0;

fun layer [] = Empty

| layer (x::xs) =

Union(x,Trans((2.0,0.0),layer xs));

val r1 = Trans((~2.0,0.0),layer[c,c,c]);

the meaning of a region
y
  • x
The meaning of a region
  • The meaning of a region is a set of points in the 2-D plane.
  • Most regions have an infinite set of points
  • We can capture this by using a characteristic function “P”
  • P x  true
  • P y -> false
helper functions
Helper functions

fun plus x y = x+y;

fun minus x y = x-y;

fun neg x = 0.0 - x;

fun leq x y = x <= y;

fun square x = x*x;

fun between a b c =

(leq a b) andalso (leq b c);

the meaning function
The meaning function

fun mean Empty (x,y) = false

| mean Univ (x,y) = true

| mean (Circle r) (x,y) =

(leq (plus (square x) (square y))

(square r))

| mean (Rect(w,h)) (x,y) =

(between (neg w) (plus x x) w)

andalso

(between (neg h) (plus y y) h)

| mean (Trans((a,b),r)) (x,y) =

mean r (minus x a,minus y b)

| mean (Inter(a,b)) pt =

(mean a pt) andalso (mean b pt)

| mean (Union(a,b)) pt =

(mean a pt) orelse (mean b pt);

staging the meaning function
Staging the meaning function

fun mean2 Empty (x,y) =

| mean2 Univ (x,y) =

| mean2 (Circle r) (x,y) =

| mean2 (Rect(w,h)) (x,y) =

<(between (neg w) (plus ~x ~x) ~(lift w))

andalso

(between (neg h) (plus ~y ~y) ~(lift h))>

| mean2 (Trans((a,b),r)) (x,y) =

mean2 r (

,)

| mean2 (Inter(a,b)) pt =

<~(mean2 a pt) andalso ~(mean2 b pt)>

| mean2 (Union(a,b)) pt =

<~(mean2 a pt) orelse ~(mean2 b pt)>;

the results of val tr1 fn x y mean2 r1 x y
The results ofval tr1 = ~(mean2 r1 (,))>;

-| val tr1 =

<(fn (b,a) =>

if %leq

(%plus (%square (%minus b (~2.0))) (%square (%minus a (0.0))))

(%square (1.0))

then true

else if if %leq

(%plus

(%square (%minus (%minus b (~2.0)) (2.0)))

(%square (%minus (%minus a (0.0)) (0.0))))

(%square (1.0))

then true

else if if %leq

(%plus

(%square

(%minus (%minus (%minus b (~2.0)) (2.0)) (2.0)))

(%square

(%minus (%minus (%minus a (0.0)) (0.0)) (0.0))))

(%square (1.0))

then true

else false

then true

else false

then true

else false)>

: <(real * real) -> bool>

problems
Problems
  • (if x then true else false)
  • (minus x 0)
  • (if (if a then b else c) then x else y)
  • (square 1.0)
  • Code duplication. (minus b 2.0) occurs many times.
what cause this
What cause this?
  • The if-then-else come from the “andalso” and the “orelse”
  • We might do better to introduce two operators
    • conj x y = x andalso y
    • disj x y = x orelse y

| mean3 (Inter(a,b)) pt =

| mean3 (Union(a,b)) pt =

;

we now get but not much better
We now get, but not much better

<(fn (b,a) =>

%disj

(%leq

(%plus (%square (%minus b (~2.0)))

(%square (%minus a (0.0))))

(%square (1.0)))

(%disj

(%leq

(%plus

(%square (%minus (%minus b (~2.0)) (2.0)))

(%square (%minus (%minus a (0.0)) (0.0))))

(%square (1.0)))

(%disj

(%leq

(%plus

(%square (%minus (%minus (%minus b (~2.0))

(2.0)) (2.0)))

(%square (%minus (%minus (%minus a (0.0))

(0.0)) (0.0))))

(%square (1.0)))

false)))>

: <(real * real) -> bool>

define staged datatypes
Define staged datatypes

datatype Sreal

= Rknown of real

| Rminus of Sreal * real

| Rplus of Sreal*Sreal

| Rsquare of Sreal

| Rneg of Sreal

| Rcomplex of ;

datatype Sbool

= Bknown of bool

| Bconj of Sbool * Sbool

| Bdisj of Sbool * Sbool

| Bbetween of Sreal * Sreal * Sreal

| Bleq of Sreal*Sreal;

from staged datatype to code
From staged datatype to code
  • The staged datatype is an abstract version of the type of answers (the abstraction)
  • It contains more information than , but less information then answer
  • This means we can translate from the staged datatype to but not from the abstraction to answer.
  • This is called “concretion”
abstraction forms a lattice
Abstraction forms a lattice

  • Top of the lattice nothing is known in the first stage.
  • At the bottom everything is known
  • Between we have varying degrees of knowledge.

Rplus(,)

Rknown 4

Rplus(,)

Rplus(,3)

real

concretion functions
Concretion functions

fun concReal (Rknown r) = lift r

| concReal (Rminus(x,y)) =

<~(concReal x) - ~(lift y)>

| concReal (Rplus(x,y)) =

< ~(concReal x) + ~(concReal y) >

| concReal (Rsquare x) =

| concReal (Rneg x) =

| concReal (Rcomplex z) = z;

fun concBool (Bknown r) = lift r

| concBool (Bconj(x,y)) =

| concBool (Bdisj(x,y)) =

| concBool (Bbetween(x,y,z)) =

~(concReal y) ~(concReal z) >

| concBool (Bleq(x,y)) =

;

optimizing functions
Optimizing functions
  • With the extra information we can build smart abstraction building functions

fun rminus x 0.0 = x

| rminus x y = Rminus (x,y);

fun rsquare (Rknown 1.0) = Rknown 1.0

| rsquare x = Rsquare x;

fun bconj (Bknown true) x = x

| bconj x (Bknown true) = x

| bconj (Bknown false) _ = Bknown false

| bconj _ (Bknown false) = Bknown false

| bconj x y = Bconj(x,y);

now redo the generator
Now redo the generator

Not the use of the optimizing constructors

fun mean4 Empty (x,y) = Bknown false

| mean4 Univ (x,y) = Bknown true

| mean4 (Circle r) (x,y) =

bleq (rplus (rsquare x) (rsquare y))

(rsquare (Rknown r)

| mean4 (Rect(w,h)) (x,y) =

bconj (bbetween (Rneg (Rknown w))

(rplus x x)

(Rknown w))

(bbetween (Rneg (Rknown h))

(rplus y y)

(Rknown h))

| mean4 (Trans((a,b),r)) (x,y) =

mean4 r (rminus x a,rminus y b)

| mean4 (Inter(a,b)) pt = bconj (mean4 a pt) (mean4 b pt)

| mean4 (Union(a,b)) pt = bdisj (mean4 a pt) (mean4 b pt);

val tr3 fn x y concbool mean4 r1 rcomplex x rcomplex y
val tr3 = ~(concBool (mean4 r1 (Rcomplex ,Rcomplex )))>;

-| val tr3 =

<(fn (b,a) =>

%disj

(%leq ((%square ((b %- ~2.0)) %+ %square a)) (1.0))

(%disj

(%leq ((%square (((b %- ~2.0) %- 2.0)) %+ %square a)) (1.0))

(%leq ((%square ((((b %- ~2.0) %- 2.0) %- 2.0)) %+ %square a)) (1.0))))>

: <(real * real) -> bool>

  • Better but we still have the duplicate code problem. This requires a different approach.
gib a generalization of fibbonacci
Gib – a generalization of fibbonacci

fun plus n x y = x+y;

fun gib (n,x,y) =

case n of

0 => Return mm x

| 1 => Return mm y

| _ =>

Do mm { a1 <- gib (n-2,x,y)

; a2 <- gib (n-1,x,y)

; Return mm

};

Note that plus does not use its first argument “n”. We use the first argument to plus as a marker

fun testgib n fn x y runmm gib n x y testgib 6
fun testGib n = ~(runMM (gib (n,,)))>;testGib 6;

Note the code duplication. It doesn’t come from our staging duplicating code, but from the way the algorithm works

val it =

<(fn (b,a) =>

%plus

6

(%plus 4 (%plus 2 b a)

(%plus 3 a (%plus 2 b a)))

(%plus 5

(%plus 3 a (%plus 2 b a))

(%plus 4 (%plus 2 b a)

(%plus 3 a (%plus 2 b a)))))>

: <('1 * '1 ) -> '1 >

classic case for memoization
Classic case for Memoization

fun gib_ksp (n,x,y) =

Do mm

{ a <- look n

; case a of

SOME z => Return mm z

| NONE => case n of

0 => Return mm x

| 1 => Return mm y

| _ =>

Do mm

{ a1 <- gib_ksp (n-2,x,y)

; a2 <- gib_ksp (n-1,x,y)

; memo n < plus ~(lift n) ~a1 ~a2 >

}

};

Memo looks up the answer stored under “n” and uses it if its there. If not, it computes an answer and stores it in the table.

observe
Observe

fun test_ksp n =

~(runMM (gib_ksp (n,,)))>;

test_ksp 6;

val it =

<(fn (b,a) =>

let val c = %plus 2 b a

val d = %plus 3 a c

val e = %plus 4 c d

val f = %plus 5 d e

val g = %plus 6 e f

in g end)>

: <('1 * '1 ) -> '1 >

Where did the “let”s come from?

questions
Questions
  • Can we somehow hide the messiness of this?
  • Can we make it work with the abstraction mechanism we used in the Region language?
a monad can hide somethings
A Monad can hide somethings
  • The table that code is stored in
    • The table is indexed by “n”
  • The ability to locally name things using “let”, and then use the name instead of the code.
better yet
Better Yet

The try2 function hides the case analysis. Note the code looks just like the original

fun gib_best (n,x,y) = try2 n

(case n of

0 => Return mm x

| 1 => Return mm y

| _ => Do mm { a1 <- gib_best (n-2,x,y)

; a2 <- gib_best (n-1,x,y)

; Return mm });

fun test_best n =

~(runMM (gib_best (n,,)))>;

test_best 6;

<(fn (b,a) =>

let val c = %plus 2 b a

val d = %plus 3 a c

val e = %plus 4 c d

val f = %plus 5 d e

val g = %plus 6 e f

in g end)>

slide28
try2

fun try2 n exp =

Do mm { a <- look n

; case a of

SOME z => Return mm z

| NONE => Do mm { ans <- exp

; memo n ans}

};

the monad
The Monad
  • ‘a is what’s computed
  • ‘s is the memo table
  • ‘c is what we eventually want

datatype ('a,'s,'c) mm =

MM of ('s -> ('s -> 'a -> 'c) -> 'c);

fun unMM (MM f) = f;

fun mmReturn a = MM (fn s => fn k => k s a);

fun mmBind (MM a) f =

MM(fn s => fn k => a s

(fn s' => fn b => unMM (f b) s' k));

val mm = Mon(mmReturn,mmBind);

operation in the monad
Operation in the monad
  • Find some thing in the memo table

fun look x =

let fun h s k = k s (lookup s x)

in MM h end;

  • Add some value “x” to table indexed under “n”

fun memo n x =

let fun h s k =

in ~(k (ext s (n,)) ) end>

in MM h end;

His is where the “let”s are generated.

just name it
Just name it

fun name x =

let fun h s k =

) end>

in MM h end;

for example
For example

fun pow 0 i = Return mm <1>

| pow 1 i = Return mm i

| pow n i =

if even n

then Do mm { x <- pow (n div 2) i

; Return mm < ~x * ~ x> }

else Do mm { x <- pow (n-1) i

; Return mm < ~i * ~ x> }

<(fn a => a %* a %* a %* a %* a %*

a %* a %* a %* a %* a)>

compare with
Compare with

fun powN 0 i = Return mm <1>

| powN 1 i = Return mm i

| powN n i =

if even n

then Do mm { x <- powN (n div 2) i

; name < ~x * ~ x> }

else Do mm { x <- powN (n-1) i

; name < ~i * ~ x> }

<(fn a =>

let val b = a %* a

val c = b %* b

val d = a %* c

val e = d %* d

in e end)>

adding abstract code
Adding Abstract Code
  • Like before, Abstract code is a staged datatype for arithmetic expressions.

datatype 'a Code

= Simple of < 'a > (* a variable *)

| Complex of < 'a > (* a non-trivial exp *)

| Known of 'a

| Factor of real * 'a Code

| Neg of 'a Code;

optimization
Optimization
  • Optimization has two parts.
    • A walk over the whole tree to reach every node
    • Applying the smart constructors that apply local optimizations for each kind of node.
    • The “smart constructors” are italized (and in red if you’re viewing this in color)
abstraction optimization
Abstraction Optimization

fun compress (Simple x) = Simple x

| compress (Complex x) = Complex x

| compress (Known x) = Known x

| compress (Add(x,y)) =

let fun help (a as (Factor(n,x)))

(b as (Add(Factor(m,y),z))) =

if n=m then help (Factor(n,add x y)) z

else add a b

| help a b = add a b

in cast (help (cast (compress x))

(cast (compress y))) end

| compress (Sub(x,y)) =

cast (sub (cast(compress x)) (cast(compress y)))

| compress (Factor(n,x)) =

cast (mult (cast (Known n)) (cast (compress x)))

example smart constructor
Example smart constructor

fun mult (Known 0.0) y = Known 0.0

| mult y (Known 0.0) = Known 0.0

| mult (Known 1.0) y = y

| mult y (Known 1.0) = y

| mult (Known ~1.0) (Sub(a,b)) = sub b a

| mult (Sub(a,b)) (Known ~1.0) = sub b a

| mult (Known a) (Factor(b,x)) = mult (Known (a*b)) x

| mult (Factor(b,x)) (Known a) = mult (Known (a*b)) x

| mult (Known x) c = Factor(x,c)

| mult c (Known x) = Factor(x,c)

| mult (Factor(c,x)) (Factor(d,y)) = Factor(c*d,mult x y)

| mult (Factor(n,c)) d = Factor(n,mult c d)

| mult d (Factor(n,c)) = Factor(n,mult c d)

| mult x y =

Complex < ~(cast(conc (cast x))) * ~(cast(conc (cast y))) >

details
Details
  • In fact, the optimizer (compress) and the smart constructors (add,sub,mult), and the concretion function must be mutually recursive since they call each other.
the concretion function
The concretion function

fun conc x =

let fun f (Simple x) = x

| f (Complex x) = x

| f (Known x) = lift x

| f (Factor(~1.0,c)) =

cast < unmin ~(cast (conc c)) >

| f (Factor(n,c)) =

cast < ~(lift n) * ~(cast (conc c)) >

| f (Add(x,y)) =

cast < ~(cast(conc x)) + ~(cast(conc y)) >

| f (Sub(x,y)) =

cast < ~(cast(conc x)) - ~(cast(conc y)) >

in f x end

working together
Working together
  • The Monad and the abstract code can be made to work together.

nameC : 'c Code -> ('c Code,'a ,<'b >) mm

fun nameC x =

let fun f (x as (Simple _)) = mmReturn x

| f (x as (Known _)) = mmReturn x

| f (x as (Factor(~1.0,Simple _))) = mmReturn x

| f (x as (Factor(_,Simple _))) = mmReturn x

| f (Factor(n,a)) =

MM(fn s => fn k =>

in ~(k s (Factor(n,Simple ))) end>)

| f x = MM(fn s => fn k =>

in ~(k s (Simple )) end>)

in f (compress x) end;

ad