|
|
last edited 2 years ago by test1 |
1 | ||
Editor: test1
Time: 2022/06/06 15:02:28 GMT+0 |
||
Note: |
changed: - Computing value of following polynomial was proposed as a benchmark: \begin{axiom} p := x^24+32*x^21+9*x^18+34*x^12+34*x^10+45*x^3 \end{axiom} Naive solution have unimpressive speed: \begin{axiom} )set messages time on [eval(p, x, 0.5) for i in 1..1000]; \end{axiom} Simple reformulations do not give better results. However, assuming that we need double precision floating point results we can turn p into a compiled function. First we convert polynomial to use doubles as coefficients: \begin{axiom} pf := p::POLY(DoubleFloat) \end{axiom} Then we define corresponding function: \begin{axiom} function(pf, 'dff, 'x) \end{axiom} Now try it: \begin{axiom} v := 0.5::SF [dff(v) for i in 1..10000]; \end{axiom} Now it is much better, but still slow. Main cost is interpreter loop. Try driver function: \begin{axiom} do_it(v, n) == (res : SF := 0; for i in 1..n repeat res := res + dff(v); res) do_it(v, 1000000) \end{axiom} This is much better, around half microsecond per evaluation, but still slower than machine arithmetic. Profiling (not shown here) indicated that 99% of time is spent in exponentiation routine. So we would need better formula like Horner rule.
Computing value of following polynomial was proposed as a benchmark:
(1) -> p := x^24+32*x^21+9*x^18+34*x^12+34*x^10+45*x^3
(1) |
Naive solution have unimpressive speed:
)set messages time on
[eval(p,x, 0.5) for i in 1..1000];
Time: 0.04 (IN) = 0.05 sec
Simple reformulations do not give better results. However, assuming that we need double precision floating point results we can turn p into a compiled function. First we convert polynomial to use doubles as coefficients:
pf := p::POLY(DoubleFloat)
(2) |
Time: 0 sec
Then we define corresponding function:
function(pf,'dff, 'x)
(3) |
Time: 0 sec
Now try it:
v := 0.5::SF
(4) |
Time: 0 sec [dff(v) for i in 1..10000];
Compiling function dff with type DoubleFloat -> DoubleFloat
Time: 0.03 (EV) = 0.03 sec
Now it is much better, but still slow. Main cost is interpreter loop. Try driver function:
do_it(v,n) == (res : SF := 0; for i in 1..n repeat res := res + dff(v); res)
Time: 0 sec do_it(v,1000000)
Compiling function do_it with type (DoubleFloat,PositiveInteger) -> DoubleFloat
(5) |
Time: 0.31 (EV) = 0.32 sec
This is much better, around half microsecond per evaluation, but still slower than machine arithmetic. Profiling (not shown here) indicated that 99% of time is spent in exponentiation routine. So we would need better formula like Horner rule.