1 / 44

Optimización automática de programas

Optimización automática de programas. Tema 3: Funciones, tipos y expresiones 3.1. Intérpretes, compiladores y tiempos de ejecución 3.2. El λ -cálculo sin tipos 3.3. Tres mini-lenguajes de programación. 3.1. Intérpretes, compiladores y tiempos de ejecución. Semántica operacional

Download Presentation

Optimización automática de programas

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. Optimización automática de programas Tema 3: Funciones, tipos y expresiones 3.1. Intérpretes, compiladores y tiempos de ejecución 3.2. El λ-cálculo sin tipos 3.3. Tres mini-lenguajes de programación Germán Vidal

  2. 3.1. Intérpretes, compiladores y tiempos de ejecución • Semántica operacional • describe las normas que rigen la ejecución de un programa • similar a la idea de intérprete • Lenguajes de programación • expresamos el “significado” de un programa (escrito en el lenguaje L) como una función que, a partir de una entrada, devuelve una salida: [[p]]L : input  output Germán Vidal

  3. Intérpretes y compiladores • Intérpretes • definición ecuacional: [[p]]S [input] = [[int]]L [p,input] • notación: • Compiladores • definición ecuacional: [[p]]S [input] = [[[[comp]]L [p]]]T [input] • notación: S L S  T L Germán Vidal

  4. Tiempos de ejecución • Estimación: suele usarse el número de operaciones “elementales”: • acceso al valor de una variable • llamada a función • pattern-matchings • operaciones aritméticas, etc, etc • por ejemplo, el coste de evaluar la expresión x + (2 * y) sería de 5 operaciones elementales • (acceso a “x”, acceso a “y”, recuperar valor de una constante, operación “+” y operación “*”) • notación: tp(d1,…,dn) Germán Vidal

  5. Tiempos de ejecución de un intérprete • El valor de una expresión, e.g., x + 2 * y, depende del valor de sus variables • consideramos un “entorno” que almacena el valor actual de cada variable del programa: env: Variable  Value • así, la función que evalúa una expresión sería: eval: Expression x Environment  Value Germán Vidal

  6. Tiempos de ejecución de un intérprete • En general, existen 2 alternativas para evaluar las expresiones de un lenguaje: • por sustitución: se reemplazan todas las variables por sus valores • mediante entorno: se mantienen los valores en el entorno y sólo se reemplazan las variables por sus valores cuando es necesario Germán Vidal

  7. Ejemplo data exp = Num int | Var string | Add exp exp | Mul exp exp eval (Num n) env = n eval (Var v) env = env v eval (Add e1 e2) env = (eval e1 env) + (eval e2 env) eval (Mul e1 e2) env = (eval e1 env) * (eval e2 env) E.g., evaluamos x+(2*y) con env = [x5, y7]: eval (Add (Var “x”) (Mul (Num 2) (Var “y”))) env  (eval (Var “x”) env) + (eval (Mul …) env)  (env “x”) + (eval (Mul (Num 2) (Var “y”)) env)  5 + (eval (Mul (Num 2) (Var “y”)) env)  5 + ((eval (Num 2) env) * (eval (Var “y”) env))  5 + (2 * (eval (Var “y”) env))  5 + (2 * (env “y”))  5 + (2 * 7)  5 + 14  19 Germán Vidal

  8. Sobrecarga de interpretación • Si exp = x + (2 * y), entonces • texp() = 5 • tint(exp) = 9 (contad el número de ) • En general, tint(p,d1,…,dn) = α * tp(d1,…,dn) siendo α la llamada “sobrecarga de interpretación” • su valor, para intérpretes reales, oscila entre 3 y 200, dependiendo del lenguaje… Germán Vidal

  9. 3.2. λ-cálculo sin tipos • Alonzo Church se preguntaba… • ...qué funciones matemáticas se pueden computar de forma mecánica (i.e., mediante un algoritmo)? • Su respuesta fue: aquéllas que se pueden especificar en el λ-cálculo (creado por él, 1930) • El λ-cálculo constituye la base teórica de casi todos los lenguajes funcionales • Lisp, Scheme, ML, Haskell, etc Germán Vidal

  10. Notación λ para las funciones • Notación básica: λx.exp (ó λx  exp ó \x -> exp) • Se trata de una función “anónima” (sin nombre) con un solo parámetro, x, cuyo cuerpo es exp • Por ejemplo, (λx.x+1) 1 = 2 • Si hay varios parámetros, podemos usar: λ(x1,x2,…,xn).exp  λx1.λx2.….λxn.exp • También se pueden indicar los tipos: λ(x1:A1,x2:A2,…,xn:An).exp Germán Vidal

  11. Ejemplos square = \x -> x*x suma = \x,y -> x+y k = \m,n -> (m+n, m-n) twice = \f -> (\x -> f(f(x))) add = \x -> (\y -> x+y) ... Germán Vidal

  12. Sintaxis del λ-cálculo (extendido) <Lam> ::= <Constant> | <Var> | <Lam> <Lam> | \<Var> -> <Lam> | if <Lam> then <Lam> else <Lam> | <Op> <Lam> ... <Lam> donde <Op> es un operador básico (e.g. +, -, *, ...) Germán Vidal

  13. Evaluación de λ-expresiones • Idea básica: • reescribimos (toda o parte de) la expresión inicial mediante una serie de reducciones hasta que se alcanza un valor • usamos la notación: M  P, para indicar que M se reduce a P Germán Vidal

  14. Algunos conceptos previos… • Ocurrencia ligada de una variable: • una ocurrencia de la variable x está ligada en una expresión si aparece dentro del ámbito de una lambda • e.g., x está ligada en \x -> x+1 • Ocurrencia libre de una variable: • si no está ligada, • e.g., x es libre en \y -> x+y Germán Vidal

  15. Algunos conceptos previos… • Variable libre: • una variable x es libre en una expresión si existe al menos una ocurrencia libre de x • e.g., x es libre en \y -> x (\x -> x) pero no en \y -> (\x -> x) • Sustitución: • son funciones finitas que denotan la asignación de expresiones a variables libres • así, [N/x]M denota la expresión M en la que las ocurrencias de la variable x se han sustituido por N • también se suele usar M[x/N] o, más a menudo, M[x  N] (nosotros usaremos la última opción!) Germán Vidal

  16. Ejercicio 3.1 • Identifica las ocurrencias de variables libres y ligadas en las siguientes expresiones • para las ligadas, indica la lambda que le afecta 1.- (x (\x -> (\x -> x x)) x) 2.- (x (\x -> (\x -> x) x) x) 3.- \h->(\x->h (x x)) (\x->h (x x)) Germán Vidal

  17. Reglas de reducción • α-conversión: \x -> M  \y -> M[x  y] donde y no debe ser libre en M • Se emplea para renombrar las variables y evitar el “problema de la captura de nombres de variables” (luego lo vemos…) Germán Vidal

  18. Reglas de reducción • β-reducción: (\x -> M) N  M[x  N] • Representa la aplicación de una función a un argumento • Restricción: • ninguna variable libre de N puede convertirse en ligada tras el paso de β-reducción (problema de la captura de nombres de variables) • se puede evitar con un paso de α-conversión (luego vemos un ejemplo..) Germán Vidal

  19. Reglas de reducción • δ-reducción: op a1 a2 ... an b si b es el resultado de aplicar el operador op sobre las constantes a1, a2, …, an • E.g., (+ 5 6)  11 • Restricción: • los argumentos debe ser constantes Germán Vidal

  20. Reglas de reducción • Reducción de condicional: if true then M else N  M if false then M else N  N Germán Vidal

  21. Reglas de reducción • Reducción en contextos: ...M...  ...N... si M  N • Significa que es correcto reducir una parte de una expresión, dejando el resto tal cual Germán Vidal

  22. Reglas de reducción • Reducción repetida: M1 M3si M1 M2 y M2  M3 • Básicamente, coincide con la propiedad transitiva… • También lo denotaremos así: M1 M2  M3  ... Germán Vidal

  23. Ejemplo (\x -> ((\x -> x+x)5)+x+(\x -> x*x)3)4  (\x -> ((5+5)+x+(\x -> x*x)3)4  (\x -> (10+x+(\x -> x*x)3)4  10+4+(\x -> x*x)3  10+4+(3*3)  14+(3*3)  14+9  23 Germán Vidal

  24. Ejercicio 3.2 • Usad las reglas de α- y β-reducción para reducir las siguientes expresiones 1. x ((\y -> x) z) 2. (\x -> x y) (\z -> z) 3. (\y -> (\z -> z y)) (\k -> z) 4. (\x -> (\y -> x y) x) (\x -> z) 5. (\f-> (\g -> (\x -> f x (g x)))) (\x->(\y->x))(\x->(\y->x)) a Germán Vidal

  25. Concepto de redex • Un redex (reducible expression) es: • cualquier expresión que se puede reducir mediante una β-reducción, una δ-reducción o una reducción de condicional • Un redex top-level es: • un redex que no se encuentra dentro del ámbito de una lambda • Una expresión está en weak head normal form (whnf) si • es una constante, e.g., 17 • una función, e.g., \x -> M • una variable libre, e.g., x • o la aplicación de una variable libre a una expresión, e.g., x M Germán Vidal

  26. Concepto de redex • Si una expresión está en whnf • no tiene top-level redexes • Existen expresiones que nunca alcanzan la whnf • e.g., (\y -> y y) (\y -> y y) • Ejemplo de captura de nombres: (\x -> 2 + (\y -> x + y) 5) (y + 1)  2 + (\y -> (y + 1) + y) 5)  2 + (5 + 1) + 5  ...  13 Error! Germán Vidal

  27. Evaluación CBV y CBN • Aunque nos limitemos a la reducción de top-level redexes, existen 2 posibilidades: • reducir primero “el argumento” de una función antes de su evaluación (CBV, call by value) • reducir primero la aplicación de una función (CBN, call by name) Germán Vidal

  28. Evaluación CBV y CBN • CBV: • para aplicar una β-reducción a (\x -> N) M, antes hay que reducir la expresión M a whnf • CBN: • podemos reducir (\x -> N) M sin necesidad de reducir previamente M a una whnf Germán Vidal

  29. CBV vs CBN • En principio, CBN es preferible porque se cumple la “propiedad de completitud”: • si existe alguna posibilidad de reducir M a una whnf P, entonces la estrategia CBN reduce M a P • probad: (\x -> 1) ((\y -> y y) (\y -> y y)) • Sin embargo, CBV puede ser más eficiente que CBN! • probad a reducir, e.g., (\x -> x + x + x) (2+2) • La mejor solución: usar CBN con “sharing”… (base de Haskell, LML, etc) Germán Vidal

  30. Ejercicio 3.3 • Encontrad 2 expresiones M y N tales que • M se evalúe más rápido con CBV que con CBN • N se evalúe más rápido con CBN que con CNV Germán Vidal

  31. Ejercicio 3.5 • Una expresión está en forma normal si no es posible realizar un paso de β-reducción, δ-reducción o reducción de condicional sobre cualquier sub-expresión (no necesariamente un top-level redex) • Encontrad una expresión P sin variables libres cuya reducción a forma normal requiera algún renombramiento mediante α-conversion Germán Vidal

  32. 3.3 Tres mini-lenguajes de programación • Un intérprete para el λ-cálculo CBV sin tipos • Un intérprete para ecuaciones recursivas de primer orden (CBV) • Un intérprete para un lenguaje imperativo simple Germán Vidal

  33. Un intérprete para el λ-cálculo CBV sin tipos data lambda = Int int // constante | Var string // variable | Abs string lambda // lambda | Apply lambda lambda // aplicación | Op string [lambda] // operador | If lambda lambda lambda // condicional type environment = ([string],[value]) data value = Numb int | Closure lambda environment Germán Vidal

  34. Un intérprete para el λ-cálculo CBV sin tipos // función principal: interpret :: lambda -> value interpret e = eval e ([],[]) // ([],[]) es el entorno “vacío” // función auxiliar: lookup :: a -> ([a],[b]) -> b lookup x (n:ns,v:vs) = if x == n then v else lookup x (ns,vs) Germán Vidal

  35. Un intérprete para el λ-cálculo CBV sin tipos eval :: lambda -> environment -> value eval (Int n) env = Numb n eval (Var x) env = lookup x env eval (Abs x e) env = Closure (Abs x e) env eval (Apply f e) env = let v = eval e env Closure (Abs x e1) (ns,vs) = eval f env in eval e1 (x:ns,v:vs) Germán Vidal

  36. Un intérprete para el λ-cálculo CBV sin tipos eval (Op “+” [e1,e2]) env = let Numb v1 = eval e1 env Numb v2 = eval e2 env in Numb (v1 + v2) // similar para “-”, “*”, etc eval (If c e1 e2) = case (eval c env) of (Numb 1) -> eval e1 env // 1 es True (Numb _) -> eval e2 env // el resto False Germán Vidal

  37. Ejercicio 3.8 • Escribe un intérprete para el λ-cálculo CBN sin tipos Germán Vidal

  38. Un intérprete para ecuaciones recursivas de primer orden (CBV) // prog = // ([nombres_funcion],[([lista_vars],cuerpo)]) type prog = ([string], [([string],expr)]) data expr = Int int // constante | Var string // variable | If expr expr expr // condicional | Call string [expr] // llamada func. | Op string [expr] // operador Germán Vidal

  39. Un intérprete para ecuaciones recursivas… // función principal (value = int): interpret :: prog -> [expr] -> int interpret pgm [args] = let (_, (vars,exp):_) = pgm in eval exp (vars,args) pgm // asumimos que la ejecución comienza con // la primera función, por eso sólo pasamos // los argumentos... Germán Vidal

  40. Un intérprete para ecuaciones recursivas… // función auxiliar: lookup :: a -> ([a],[b]) -> b lookup x (n:ns,v:vs) = if x == n then v else lookup x (ns,vs) // función auxiliar: evlist ::[exp]->([string],[int])->prog->int evlist [] _ _ = [] evlist (e:es) env pgm = (eval e env pgm) : (evlist es env pgm) Germán Vidal

  41. Un intérprete para ecuaciones recursivas… eval ::exp->([string],[int])->prog->int eval (Int n) env pgm = n eval (Var x) env pgm = lookup x env eval (Call f exps) env pgm = let vals = evlist exps env pgm (vars,exp) = lookup f pgm in eval exp (vars,vals) pgm Germán Vidal

  42. Un intérprete para ecuaciones recursivas… eval (Op “+” [e1,e2]) env pgm = (eval e1 env pgm) + (env e2 env pgm) // similar para “-”, “*”, etc eval (If c e1 e2) env pgm = case (eval c env pgm) of 1 -> eval e1 env pgm // 1 es True _ -> eval e2 env pgm // resto False Germán Vidal

  43. Ejercicio 3.9 • Escribe un intérprete para ecuaciones recursivas de primer orden CBN Germán Vidal

  44. Un intérprete para un lenguaje imperativo simple • No lo vemos en clase… (lo podéis encontrar en [Jones, Gomard, Sestoft 93]) Germán Vidal

More Related