Experiments by María Alpuente, Santiago Escobar and Salvador Lucas.
We first give some examples with redundant arguments, borrowed from the literature and/or obtained by applying common transformation processes. Redundant arguments in these program examples are highlighted in red. Then we show the result of applying our Automatic Useless Argument Elimination System to these benchmarks. Finally, we present the improvement achieved by our system w.r.t. original examples by showing a table with runtimes of the original and optimized programs.
Examples with redundant arguments
Example from the literature on useless variable elimination (UVE), a popular technique for removing dead variables.
|
|
|
data nat = Z | S nat loop :: nat -> nat -> nat -> nat loop a bogus Z = loop (S a) (S bogus) (S Z) loop a bogus (S x) = a |
Examples from [AG01]
|
|
|
data nat = Z | S nat f :: nat -> nat -> nat f Z y = Z f (S x) y = f (f x y) y |
|
data nat = Z | S nat f :: nat -> nat f Z = S Z f (S Z) = S Z f (S (S x)) = f (f (S x)) |
Examples from program specialization
|
|
|
|
|
data Nat = 0 | S Nat append::[Nat] -> [Nat] -> [Nat] append nil y = y append (x:xs) y = x:(append xs y) last::[Nat] -> Nat last (x:nil) = x last (x:y:ys) = last (y:ys) |
last (append xs (x:nil)) |
applast::[Nat] -> Nat -> Nat applast nil z = z applast (x:xs) z = lastnew x xs z lastnew::Nat -> [Nat] -> Nat -> Nat lastnew x nil z = z lastnew x (y:ys) z = lastnew y ys z |
|
data nat = Z | S nat plus :: nat -> nat -> nat plus Z x = x plus (S x) y = S (plus x y) minus :: nat -> nat -> nat minus x Z = x minus (S x) (S y) = minus(X,Y) |
minus (plus x y) x |
minus_pe :: nat -> nat -> nat minus_pe Z y = y minus_pe (S x) y = minus_pe x y |
|
data nat = Z | S nat plus :: nat -> nat -> nat plus Z x = x plus (S x) y = S (plus x y) leq :: nat -> nat -> Bool leq Z x = True leq (S x) Z = False leq (S x) (S y) = leq x y |
leq x (plus x y) |
leq_pe :: nat -> nat -> Bool leq_pe Z x = True leq_pe (S x) y = leq_pe x y |
|
data nat = Z | S nat double :: nat -> nat double Z = Z double (S x) = S (S (double x)) even :: nat -> Bool even Z = True even (S Z) = False even (S (S x)) = even x |
even (double x) |
even_pe :: nat -> Bool even_pe Z = True even_pe (S x) = even_pe x |
|
data nat = Z | S nat min :: nat -> nat -> nat min Z x = Z min (S x) Z = Z min (S x) (S y) = S (min x y) minimal :: [nat] -> nat minimal (x:nil) = x minimal (x:y:xs) = min x (minimal (y:xs)) append :: [Nat] -> [Nat] -> [Nat] append nil y = y append (x:xs) y = x:(append xs y) |
minimal (append (Z:nil) xs) |
minimal_pe :: nat -> nat minimal_pe nil = Z minimal_pe (x:y) = Z |
|
data nat = Z | S nat plus :: nat -> nat -> nat plus Z x = x plus (S x) y = S (plus x y) sum :: [nat] -> nat sum nil = Z sum (x:xs) = plus x (sum xs) allzeros :: [nat] -> [nat] allzeros nil = nil allzeros (x:xs) = Z:(allzeros xs) |
sum (allzeros x) |
sum_pe :: [nat] -> nat sum_pe nil = Z sum_pe (x:xs) = sum_pe xs |
Experiments
Results of (automatically)
performing the analysis and elimination of redundant arguments:
First, we execute the original and transformed programs in Curry.In the case of program bogus, no appreciable optimization is achieved by removing redundant arguments, since Curry is a lazy language and the redundant argument in bogus is a useless variable.
Runtimes have been measured in a Pentium III class machine running linux and using version 1.3.2 of the PAKCS Compiler under Sicstus Prolog 3.8.4.
Natural numbers
are given by numbers 0, 1, 2, etc instead of the notation Z/S x. For bechmarking
purposes, goals make use of the factorial function, defined in a usual
way.
The number
of elements of a list is indicated by a subindex. In the case of binary
trees, the subindex indicates the depth of the tree.
|
|
|
|
|
|
|
loop (fact 8) (fact 8) (fact 8) |
|
loop' (fact 8) (fact 8) |
|
|
|
applast [(fact 8)]1000 (fact 8) |
|
applast' (fact 8) |
|
|
|
minus_pe (fact 8) (fact 8) |
|
minus_pe' (fact 8) |
|
|
|
leq_pe (fact 8) (fact 8) |
|
leq_pe' |
|
|
|
even_pe (fact 8) |
|
even_pe' |
|
|
|
minimal_pe [(fact 8)]10000 |
|
minimal_pe' |
|
|
|
sum_pe [(fact 8)]10000 |
|
sum_pe' |
|
|
|
f (fact 8) (fact 8) |
|
f' |
|
|
|
f (fact 8) |
|
f' |
|
|
Finally, we
run the programs in CiME 2, a system which
uses an innermost rewriting strategy. Note that, in this case, significant
optimizations are also measured for programs bogus, applast and plus_minus.
|
|
|
|
|
|
|
loop (fact 6) (fact 6) (fact 6) |
|
loop' (fact 6) (fact 6) |
|
|
|
applast [(fact 6)]10 (fact 6) |
|
applast' (fact 6) |
|
|
|
minus_pe (fact 6) (fact 6) |
|
minus_pe' (fact 6) |
|
|
|
leq_pe (fact 6) (fact 6) |
|
leq_pe' |
|
|
|
even_pe (fact 6) |
|
even_pe' |
|
|
|
minimal_pe [(fact 6)]10 |
|
minimal_pe' |
|
|
|
sum_pe [0]1000 |
|
sum_pe' |
|
|
|
f (fact 6) (fact 6) |
|
f' |
|
|
|
f (fact 6) |
|
f' |
|
|
[AG01] T. Arts and J. Giesl. A collection of examples for termination of term rewriting using dependency pairs. Technical Report AIB-2001-09 RWTH Aachen, 2001.
[Kob00] N. Kobayashi. Type-based useless variable elimination. In Proc. of PEPM-00, pages 84-93, ACM Press, 2000.
[WS99] M. Wand and I. Siveroni.
Constraint
systems for useless variable elimination. In Proc. of POPL'99,
pages 291--302, ACM Press, 1999.
Please, send comments or suggestions to sescobar@dsic.upv.es. Any kind of contribution is welcome.