Generate optimized code
This functionality does not run in MATLAB.
generate::optimize(r) returns a sequence
of equations representing an "optimized computation sequence"
for the input expression
r. Each equation in
the sequence corresponds to an assignment of a subexpression of the
input expression to a "temporary variable." Common subexpressions
are computed only once, thus reducing the total operation count.
The number of operations, namely additions (or subtractions), multiplications (or divisions) and in particular functions calls of the output is usually lower than the number of such operations of the input. This facility is useful for code generation.
In this first example, we show the effects of optimization for a simple expression:
generate::optimize(cos(x^2) + x^2*sin(x^2) + x^4)
The "blind" computation of the input expression
requires 7 multiplications, 2 additions and 2 function calls. The
optimized version introduces a "temporary variable"
x^2 that is used to compute the
t1. This reduces the total cost to
3 multiplications, 2 additions and 2 function calls, albeit using
1 extra assignment to the temporary variable
Here we repeat the exercise of the first example but with an array of expressions:
generate::optimize(array(1..2, 1..2, [[x^3, x^2],[x^2, x^4]]))
The original input requires 6 multiplications. The optimized version needs only 3 multiplications and 1 extra assignment.
We optimize a list of equations representing a computation sequence
for 3 variables
generate::optimize([t = u, C = t*(u - w)^2, C = 2*(u - w)^3])
The original computation requires 5 multiplications and 2 subtractions. The optimized version needs 4 multiplications and 1 subtraction.
Note that since these examples involve small expressions, the computational savings are slight. In the case of very large expressions, optimization can yield a considerable dividend.
An expression, array or list of equations
List of equations.
A number of FORTRAN compilers provide optimizers. However, they use algorithms of complexity O(n2) and O(n3) where n is the size of the input expressions. For large amounts of code, these algorithms may "break." MuPAD® provides a reasonably good scalar (as in non-vectorized and non-parallelized) optimizer which is limited to common subexpression optimization and using binary powering for integer powers. It uses hashing of expressions so that given a sub-expression, it can determine in constant time if this subexpression has already occurred. This results in an overall efficiency which is of lower complexity namely, O(n) i.e. linear in the size of the input expressions to be optimized, Hence overall efficiency is not compromised by very large expressions. This does mean that not all possible optimizations are made but nonetheless a number of reductions including the exploitation of some symmetries are possible.
It should be understood that "optimization" is
meant in the sense of compiler optimization. The end-result rarely
corresponds to the absolute irreducible minimum number of operations
– or as in the case of FORTRAN code generation, the absolute
minimum of floating-point operations (FLOPS). Achieving this limit
can be extremely difficult if not impossible especially for large
computational sequences. Nonetheless, in a number of real-life instances,
the MuPAD optimizer can yield a very useful result. Additionally, MuPAD provides
symbolic manipulation tools such as
can yield additional reduction in operation costs.
In many cases of optimization, it is most often a matter of how best to pose the problem so as to fully exploit every possible symmetry or useful natural property of the given problem.