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.

Slides:



Advertisements
Similar presentations
ML Lists.1 Standard ML Lists. ML Lists.2 Lists A list is a finite sequence of elements. [3,5,9] ["a", "list" ] [] Elements may appear more than once [3,4]
Advertisements

Type Checking, Inference, & Elaboration CS153: Compilers Greg Morrisett.
ML Lists.1 Standard ML Lists. ML Lists.2 Lists  A list is a finite sequence of elements. [3,5,9] ["a", "list" ] []  ML lists are immutable.  Elements.
ML Datatypes.1 Standard ML Data types. ML Datatypes.2 Concrete Datatypes  The datatype declaration creates new types  These are concrete data types,
Kathleen Fisher cs242 Reading: “A history of Haskell: Being lazy with class”,A history of Haskell: Being lazy with class Section 6.4 and Section 7 “Monads.
Control-Flow Graphs & Dataflow Analysis CS153: Compilers Greg Morrisett.
Tim Sheard Oregon Graduate Institute Lecture 8: Operational Semantics of MetaML CSE 510 Section FSC Winter 2005 Winter 2005.
CSE341: Programming Languages Lecture 16 Datatype-Style Programming With Lists or Structs Dan Grossman Winter 2013.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
0 PROGRAMMING IN HASKELL Chapter 10 - Declaring Types and Classes.
String is a synonym for the type [Char].
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Patterns in ML functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are the.
Tim Sheard Oregon Graduate Institute Lecture 4: Staging Interpreters CSE 510 Section FSC Winter 2004 Winter 2004.
CSE341: Programming Languages Lecture 12 Equivalence Dan Grossman Spring 2013.
CS412/413 Introduction to Compilers Radu Rugina Lecture 16: Efficient Translation to Low IR 25 Feb 02.
CSE341: Programming Languages Lecture 8 Lexical Scope and Function Closures Dan Grossman Fall 2011.
Cse321, Programming Languages and Compilers 1 6/12/2015 Lecture #9, Feb. 12, 2007 A data structure for grammars Computing Nullable and First in SML.
Tim Sheard Oregon Graduate Institute Lecture 6: Monads and Interpreters CSE 510 Section FSC Winter 2004 Winter 2004.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Cse321, Programming Languages and Compilers 1 6/19/2015 Lecture #18, March 14, 2007 Syntax directed translations, Meanings of programs, Rules for writing.
Tim Sheard Oregon Graduate Institute Lecture 5: Review of homework 2 CS510 Sect FSC Winter 2004 Winter 2004.
A Methodology for Generating Verified Combinatorial Circuits CSE 510 Section FSC Winter 2004 Winter 2004 Kiselyov, Swadi, Taha.
Stacks. What is a stack? A stack is a Last In, First Out (LIFO) data structure Anything added to the stack goes on the “top” of the stack Anything removed.
CS 2104 : Prog. Lang. Concepts. Functional Programming I Lecturer : Dr. Abhik Roychoudhury School of Computing From Dr. Khoo Siau Cheng’s lecture notes.
Tim Sheard Oregon Graduate Institute Lecture 6: Monadic Staging of the RE language CSE 510 Section FSC Winter 2004 Winter 2004.
ML Datatypes.1 Standard ML Data types. ML Datatypes.2 Concrete Datatypes  The datatype declaration creates new types  These are concrete data types,
Chapter Twenty-ThreeModern Programming Languages1 Formal Semantics.
Interpretation Environments and Evaluation. CS 354 Spring Translation Stages Lexical analysis (scanning) Parsing –Recognizing –Building parse tree.
Formal Semantics Chapter Twenty-ThreeModern Programming Languages, 2nd ed.1.
Lee CSCE 314 TAMU 1 CSCE 314 Programming Languages Haskell: Types and Classes Dr. Hyunyoung Lee.
Advanced Functional Programming Tim Sheard 1 Lecture 6 Functional Programming Tim Sheard & Mark Jones Monads & Interpreters.
Cs7120 (prasad)L7-TDEF1 Type Definitions. cs7120 (prasad)L7-TDEF2 Concrete Types Primitive types ( int, bool, char, string, etc ) Type constructors (
A Second Look At ML 1. Outline Patterns Local variable definitions A sorting example 2.
Advanced Functional Programming Tim Sheard 1 Lecture 18 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture.
1 CS 457/557: Functional Languages Lists and Algebraic Datatypes Mark P Jones Portland State University.
Intro to Planning Or, how to represent the planning problem in logic.
1 Compiler Construction (CS-636) Muhammad Bilal Bashir UIIT, Rawalpindi.
Error Example - 65/4; ! Toplevel input: ! 65/4; ! ^^ ! Type clash: expression of type ! int ! cannot have type ! real.
Advanced Functional Programming Tim Sheard 1 Lecture 17 Advanced Functional Programming Tim Sheard Oregon Graduate Institute of Science & Technology Lecture:
CSED101 INTRODUCTION TO COMPUTING FUNCTION ( 함수 ) 유환조 Hwanjo Yu.
CSE 341 : Programming Languages Lecture 9 Lexical Scope, Closures Zach Tatlock Spring 2014.
1.SML Docs Standard Basis 2.First-Class Functions Anonymous Style Points Higher-Order 3.Examples Agenda.
String is a synonym for the type [Char].
Principles of programming languages 12: Functional programming
ML: a quasi-functional language with strong typing
Tim Sheard Oregon Graduate Institute
PROGRAMMING IN HASKELL
CSE341: Programming Languages Lecture 8 Lexical Scope and Function Closures Dan Grossman Winter 2013.
CSE341: Programming Languages Lecture 8 Lexical Scope and Function Closures Dan Grossman Spring 2013.
Nicholas Shahan Spring 2016
CSE341: Programming Languages Lecture 12 Equivalence
Agenda SML Docs First-Class Functions Examples Standard Basis
Agenda SML Docs First-Class Functions Examples Standard Basis
CSE341: Programming Languages Lecture 8 Lexical Scope and Function Closures Dan Grossman Spring 2016.
CSE 341 Section 5 Winter 2018.
CSE341: Programming Languages Lecture 8 Lexical Scope and Function Closures Dan Grossman Autumn 2018.
CSE341: Programming Languages Lecture 12 Equivalence
CSE341: Programming Languages Lecture 12 Equivalence
Types and Classes in Haskell
PROGRAMMING IN HASKELL
CSE341: Programming Languages Lecture 8 Lexical Scope and Function Closures Zach Tatlock Winter 2018.
CSE-321 Programming Languages Introduction to Functional Programming
CSE341: Programming Languages Lecture 12 Equivalence
CSE341: Programming Languages Lecture 8 Lexical Scope and Function Closures Dan Grossman Autumn 2017.
Rehearsal: Lazy Evaluation Infinite Streams in our lazy evaluator
CSE341: Programming Languages Lecture 12 Equivalence
CSE341: Programming Languages Lecture 8 Lexical Scope and Function Closures Dan Grossman Spring 2019.
Brett Wortzman Summer 2019 Slides originally created by Dan Grossman
CSE341: Programming Languages Lecture 12 Equivalence
Presentation transcript:

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 ClassifiersML Like Inference for Classifiers –Assigned Thursday Feb 10, 2005 –To be discussed, Thursday Feb 17, 2005 –We will need a presenter …

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 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 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 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 x y

Helper functions fun plus x y = x+y; fun minus x y = x-y; fun neg x = 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 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 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 (Union(a,b)) pt = ;

The results of val tr1 = ~(mean2 r1 (, ))>; -| val tr1 = 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)> : bool>

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? –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 %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)))> : bool>

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 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 Top of the lattice nothing is known in the first stage. At the bottom everything is known Between we have varying degrees of knowledge. real Rknown 4 Rplus(,3) Rplus(, )

Concretion functions fun concReal (Rknown r) = lift r | concReal (Rminus(x,y)) = | concReal (Rplus(x,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)) = <between ~(concReal x) ~(concReal y) ~(concReal z) > | concBool (Bleq(x,y)) = ;

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 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); Not the use of the optimizing constructors

val tr3 = ~(concBool (mean4 r1 (Rcomplex,Rcomplex )))>; -| val tr3 = %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))))> : bool> Better but we still have the duplicate code problem. This requires a different approach.

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 = ~(runMM (gib (n,, )))>; testGib 6; val it = %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 > Note the code duplication. It doesn’t come from our staging duplicating code, but from the way the algorithm works

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 } }; 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 fun test_ksp n = ~(runMM (gib_ksp (n,, )))>; test_ksp 6; val it = 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 > Where did the “let”s come from?

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 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 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; 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)> The try2 function hides the case analysis. Note the code looks just like the original

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 ‘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 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 = <let val z = ~x in ~(k (ext s (n, )) ) end> in MM h end; His is where the “let”s are generated.

Just name it fun name x = let fun h s k = ) end> in MM h end;

For example fun pow 0 i = Return mm | pow 1 i = Return mm i | pow n i = if even n then Do mm { x <- pow (n div 2) i ; Return mm } else Do mm { x <- pow (n-1) i ; Return mm } a %* a %* a %* a %* a %* a %* a %* a %* a %* a)>

Compare with fun powN 0 i = Return mm | powN 1 i = Return mm i | powN n i = if even n then Do mm { x <- powN (n div 2) i ; name } else Do mm { x <- powN (n-1) i ; name } let val b = a %* a val c = b %* b val d = a %* c val e = d %* d in e end)>

Adding Abstract Code Like before, Abstract code is a staged datatype for arithmetic expressions. datatype 'a Code = Simple of (* a variable *) | Complex of (* a non-trivial exp *) | Known of 'a | Factor of real * 'a Code | Neg of 'a Code;

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 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 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

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 fun conc x = let fun f (Simple x) = x | f (Complex x) = x | f (Known x) = lift x | f (Factor(~1.0,c)) = cast | f (Factor(n,c)) = cast | f (Add(x,y)) = cast | f (Sub(x,y)) = cast in f x end

Working together The Monad and the abstract code can be made to work together. nameC : 'c Code -> ('c Code,'a, ) 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 => <let val z = ~(conc a) in ~(k s (Factor(n,Simple ))) end>) | f x = MM(fn s => fn k => <let val z = ~(conc x) in ~(k s (Simple )) end>) in f (compress x) end;