Performance - Maple Help
For the best experience, we recommend viewing online help using Google Chrome or Microsoft Edge.

Online Help

All Products    Maple    MapleSim


Performance Improvements in Maple 2024

 

Operations on Matrices Containing Quantities with Units

Floating-Point Matrix and Vector Initialization

Faster Univariate Complex Solver

RootFinding

Quantifier Elimination

Various Small Improvements

Operations on Matrices Containing Quantities with Units

• 

A new Units indexing function has been created which allows a matrix, vector, or array to keep units separate from the data.  This allows the data to be a single block of hardware type values, including datatype=float[8] and datatype=complex[8]. LinearAlgebra and other package routines can then dispatch to fast hardware algorithms providing optimal performance.

• 

Here is an example that creates a 100x100 matrix of random data, each element has the unit of meters per second.  Computing the inverse takes milliseconds, which is over a thousand times faster than the way done in previous versions which required datatype=anything.

M := LinearAlgebra:-RandomMatrix(100,datatype=float[8],shape=Unit(m/s)):

CodeTools:-Usage( LinearAlgebra:-MatrixInverse(M) ):

memory used=412.60KiB, alloc change=0 bytes, cpu time=18.00ms, real time=84.00ms, gc time=0ns

• 

A matrix with the Units indexing function can be used seamlessly in place of a matrix that has no indexing function, but keeps quantities with units. Such a matrix allows a single unit for all data, different units on different entries, and even entries with no unit assigned.  The matrix will adapt to the situation.  

M := Matrix( 2, (i,j)->(10*i+j)*Unit(kg), shape=Unit(kg) );

M11kg12kg21kg22kg

(1)

M[1,1] := 1.23 * Unit(ohm);

M1,11.23Ω

(2)

M[1,2] := 17;

M1,217

(3)

M;

1.23Ω1721kg22kg

(4)
• 

Quantities assigned into the matrix will be converted into the default unit specified for that matrix whenever possible.

M[2,2] := 35.2 * Unit(lb);

M2,235.2lb

(5)

M;

1.23Ω1721kg15.96645142kg

(6)
• 

The unit and data can be easily separated, so algorithms can inspect and take advantage of the new structure as needed. In this example we perform a matrix power by operating on just the data, and only apply a unit transformation at the end.   This kind of manipulation is used behind the scenes in many built-in operations in the LinearAlgebra package.

A := Matrix(2,(i,j)->(10*i+j)*Unit(m), shape=Unit(m), datatype=float[8] );

A11.m12.m21.m22.m

(7)

default_unit, data := op(rtable_split_unit(A));

default_unit,datam,11.12.21.22.

(8)

newA := rtable_set_indfn(data^4,Units:-Simple:-simplify(default_unit^4));

newA413557.m4439164.m4768537.m4816124.m4

(9)
• 

The Units:-Simple package makes use of this new data structure by default when possible.

with(Units:-Simple);

`*`&comma;`+`&comma;`-`&comma;`/`&comma;`<`&comma;<=&comma;<>&comma;`=`&comma;`^`&comma;arccos&comma;arccosh&comma;arccot&comma;arccoth&comma;arccsc&comma;arccsch&comma;arcsec&comma;arcsech&comma;arcsin&comma;arcsinh&comma;arctan&comma;arctanh&comma;argument&comma;collect&comma;combine&comma;cos&comma;cosh&comma;cot&comma;coth&comma;csc&comma;csch&comma;diff&comma;eval&comma;evalc&comma;evalr&comma;exp&comma;factor&comma;frem&comma;ln&comma;log&comma;log10&comma;log2&comma;max&comma;min&comma;piecewise&comma;polar&comma;root&comma;sec&comma;sech&comma;shake&comma;sin&comma;sinh&comma;sqrt&comma;surd&comma;tan&comma;tanh&comma;type&comma;verify

(10)

A := <1,2;3,4>*Unit(m);

Am2m3m4m

(11)

B := <5,6;7,8>*Unit(s);

B5s6s7s8s

(12)

C := A . B^(-1);

C3ms2ms2msms

(13)

rtable_indfns(A);

m

(14)

rtable_indfns(B);

s

(15)

rtable_indfns(C);

ms

(16)
• 

For additional improvements involving units in Maple 2024, see Improvements in Handling of Units in Maple 2024.

Floating-Point Matrix and Vector Initialization

• 

Maple uses hardware double-precision floating-point representations when constructing matrices and vectors specified with datatype=float[8]. On initialization Maple 2024 calls directly to the evalhf implementation of known functions and avoids conversion from hardware to software floats. Performance of examples such as the following has dramatically sped up.

tt:=time[real]():

signal:=Vector(10^5,i->sin(i*1.0),datatype=float[8]):

time[real]()-tt;

0.311

(17)

Faster Univariate Complex Solver

• 

Maple 2024 contains a new solver for isolating and approximating all complex roots of a univariate polynomial with numeric or complex(numeric) coefficients. This solver is available through the method=PW option of the RootFinding:-Isolate command. Except when the domain option is given, the new solver is considerably faster than the one used when method=HR is specified, in particular for high accuracy, and it is now the default when option complex is used. Here are a few examples and timing comparisons for the two solvers.

• 

Random polynomial, increasing accuracy.

f := randpoly(x, dense, coeffs=rand(-2^32+1..2^32-1), degree=512):

CodeTools:-Usage(RootFinding:-Isolate(f, digits=10, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(f, digits=10, method=PW)):

memory used=6.55MiB, alloc change=0 bytes, cpu time=161.00ms, real time=161.00ms, gc time=0ns

memory used=5.18MiB, alloc change=0 bytes, cpu time=118.00ms, real time=117.00ms, gc time=0ns

CodeTools:-Usage(RootFinding:-Isolate(f, digits=15, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(f, digits=15, method=PW)):

memory used=6.58MiB, alloc change=0 bytes, cpu time=1.66s, real time=1.66s, gc time=0ns

memory used=4.90MiB, alloc change=0 bytes, cpu time=271.00ms, real time=271.00ms, gc time=0ns

CodeTools:-Usage(RootFinding:-Isolate(f, digits=30, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(f, digits=30, method=PW)):

memory used=6.76MiB, alloc change=0 bytes, cpu time=1.73s, real time=1.73s, gc time=0ns

memory used=5.58MiB, alloc change=0 bytes, cpu time=388.00ms, real time=388.00ms, gc time=0ns

• 

Bernoulli polynomials, increasing degree.

g1 := expand(bernoulli(128,x)):

CodeTools:-Usage(RootFinding:-Isolate(g1, digits=10, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(g1, digits=10, method=PW)):

memory used=1.57MiB, alloc change=0 bytes, cpu time=7.24s, real time=7.24s, gc time=0ns

memory used=1.35MiB, alloc change=0 bytes, cpu time=1.17s, real time=1.17s, gc time=0ns

g2 := expand(bernoulli(255,x)):

CodeTools:-Usage(RootFinding:-Isolate(g2, digits=10, method=HR)):
CodeTools:-Usage(RootFinding:-Isolate(g2, digits=10, method=PW)):

memory used=3.61MiB, alloc change=0 bytes, cpu time=37.04s, real time=37.04s, gc time=0ns

memory used=2.94MiB, alloc change=0 bytes, cpu time=3.36s, real time=3.36s, gc time=0ns

RootFinding

• 

The EvaluateAtRoot command in the RootFinding package has a new option `avoidsymbolic`. Its main purpose is to improve the command's efficiency. When specified, symbolic processing to ascertain whether the given root is an exact zero of a constraint or not will be skipped. In general this will lead to weaker answers, e.g., FAIL being returned instead of true or false.

• 

In the following example, the unique root of sys contained in sysroot is actually an exact root of the non-strict inequality in cons.

vars := [x, y];

varsx&comma;y

(18)

sys := [-7*x^5+22*x^4-55*x^3-94*x^2+87*x-56,
        -10*y^5+62*y^4-82*y^3+80*y^2-44*y+71];

sys7x5+22x455x394x2+87x56&comma;10y5+62y482y3+80y244y+71

(19)

sysroot := [[-228940483906911495/144115188075855872, -57235120976727867/36028797018963968],
            [338902091289333/70368744177664, 677804182578693/140737488355328]];

sysroot228940483906911495144115188075855872&comma;5723512097672786736028797018963968&comma;33890209128933370368744177664&comma;677804182578693140737488355328

(20)

cons := [434*x^9-2043*x^8+6055*x^7-1085*x^6-10004*x^5+17167*x^4-6842*x^3+11542*x^2-6997*x <= -4648,
         -50*y^5+23*y^4+75*y^3-92*y^2+6*y+74 > 0];

cons434x92043x8+6055x71085x610004x5+17167x46842x3+11542x26997x−4648&comma;0<50y5+23y4+75y392y2+6y+74

(21)

consSet := convert(cons, 'set');

consSet434x92043x8+6055x71085x610004x5+17167x46842x3+11542x26997x−4648&comma;0<50y5+23y4+75y392y2+6y+74

(22)
• 

By default, EvaluateAtRoot uses symbolic computation to prove that the first constraint is satisfied:

CodeTools:-Usage(RootFinding:-EvaluateAtRoot(cons, sysroot, sys, vars));

memory used=3.14MiB, alloc change=0 bytes, cpu time=33.00ms, real time=34.00ms, gc time=0ns

true&comma;false

(23)

CodeTools:-Usage(RootFinding:-EvaluateAtRoot(consSet, sysroot, sys, vars));

memory used=446.16KiB, alloc change=0 bytes, cpu time=10.00ms, real time=10.00ms, gc time=0ns

false

(24)
• 

When specifying the avoidsymbolic option and giving a maximum value of 100 for the floating-point precision, the underlying numerical computation will not be able to prove that the first constraint is satisfied, and therefore FAIL is returned:

CodeTools:-Usage(RootFinding:-EvaluateAtRoot(cons, sysroot, sys, vars, 'avoidsymbolic' = true, 'threshold' = 100));

memory used=143.38KiB, alloc change=0 bytes, cpu time=3.00ms, real time=3.00ms, gc time=0ns

FAIL&comma;false

(25)
• 

Nevertheless, in the following calling sequence, where we are only interested in the truth value of the logical conjunction of the two constraints, this weaker result is still sufficient, since the 2nd constraint, and therefore the whole conjunction, is false:

CodeTools:-Usage(RootFinding:-EvaluateAtRoot(consSet, sysroot, sys, vars, 'avoidsymbolic' = true, 'threshold' = 100));

memory used=133.67KiB, alloc change=0 bytes, cpu time=3.00ms, real time=3.00ms, gc time=0ns

false

(26)

Quantifier Elimination

• 

Significant performance improvements have been made to the QuantifierElimination package, including faster evaluation at sample points by using RootFinding:-EvaluateAtRoot and caching of intermediate results.

• 

The following examples are 6-7 times faster than Maple 2023.

formula1 := forall([x,y,t], Implies(And(x^3+y^2-x=t, t^2=4/27, t<0), x^2+y^2>=rho));

formula1x&comma;y&comma;t&comma;x3+y2x=tt2=427t<0ρx2+y2

(27)

CodeTools:-Usage(QuantifierElimination:-QuantifierEliminate(formula1));

memory used=2.88GiB, alloc change=158.48MiB, cpu time=49.36s, real time=43.16s, gc time=8.52s

ρRootOf729_Z2+270_Z83&comma;6730380045934410413031180591620717411303424..26921520183737641651854722366482869645213696<0ρRootOf729_Z2+270_Z83&comma;6730380045934410413031180591620717411303424..26921520183737641651854722366482869645213696=0RootOf729_Z2+270_Z83&comma;6730380045934410413031180591620717411303424..26921520183737641651854722366482869645213696ρ<0ρRootOf27_Z218_Z13&comma;64411164140810191969147573952589676412928..10305786262529630714772361183241434822606848<0ρRootOf27_Z218_Z13&comma;64411164140810191969147573952589676412928..10305786262529630714772361183241434822606848=0RootOf27_Z218_Z13&comma;64411164140810191969147573952589676412928..10305786262529630714772361183241434822606848ρ<0ρRootOf27_Z24&comma;18176397067312372737894722366482869645213696..9088198533656186368812361183241434822606848<0ρRootOf27_Z24&comma;18176397067312372737894722366482869645213696..9088198533656186368812361183241434822606848=0RootOf27_Z24&comma;18176397067312372737894722366482869645213696..9088198533656186368812361183241434822606848ρ<027ρ<−527ρ+5=027ρ<5ρRootOf27_Z218_Z1&comma;30439693221836108653590295810358705651712..1217587728873444345852361183241434822606848<0ρRootOf27_Z218_Z1&comma;30439693221836108653590295810358705651712..1217587728873444345852361183241434822606848=0RootOf27_Z218_Z1&comma;30439693221836108653590295810358705651712..1217587728873444345852361183241434822606848ρ<0ρ<0ρ=0ρ<0ρRootOf729_Z2+270_Z83&comma;18862547901774207647059444732965739290427392..4715636975443551911832361183241434822606848<0ρRootOf729_Z2+270_Z83&comma;18862547901774207647059444732965739290427392..4715636975443551911832361183241434822606848=0RootOf729_Z2+270_Z83&comma;18862547901774207647059444732965739290427392..4715636975443551911832361183241434822606848ρ<03ρ<11+3ρ=0

(28)

formula2 := exists([t__10,t__11,t__12,t__6,b__12,t__5], And(
    0<=t__10, 0<=t__11, 0<=t__12, 0<=t__6, 0<=b__12,
    t__10<=1, t__11<=1, t__12<=1, t__6<=1, b__12<=1,
    0<t__5, t__5<1, t__5^3-2*t__5^2+t__5<0, 0<t__5^3-2*t__5^2+t__5+1,
    t__6+1-t__5=0, -t__5^2+t__10+t__5=0, t__5^2-t__11+t__12-2*t__5+1=0,
    -t__5^2+t__11+2*t__5+b__12-2 = 0));

formula2t__10&comma;t__11&comma;t__12&comma;t__6&comma;b__12&comma;t__5&comma;0t__100t__110t__120t__60b__12t__101t__111t__121t__61b__1210<t__5t__5<1t__532t__52+t__5<00<t__532t__52+t__5+1t__6+1t__5=0t__52+t__10+t__5=0t__52t__11+t__122t__5+1=0t__52+b__12+t__11+2t__52=0

(29)

CodeTools:-Usage(QuantifierElimination:-QuantifierEliminate(formula2));

memory used=2.56GiB, alloc change=0 bytes, cpu time=39.67s, real time=34.16s, gc time=7.40s

false

(30)
• 

In addition, the display of various data structures in the QuantifierElimination package has been improved.

formula := exists(x, x^2+b*x+c=0);

formulax&comma;bx+x2+c=0

(31)

C := QuantifierElimination:-PartialCylindricalAlgebraicDecompose(formula, 'output'=['data']);

CVariables&equals;c&comma;b&comma;xInput Formula&equals;x&comma;bx+x2+c=0# Cells&equals;17Projection polynomials for level 1&equals;cProjection polynomials for level 2&equals;b24cProjection polynomials for level 3&equals;bx+x2+c

(32)

GetLeafCells(C)[1..5];

Description&equals;c<0x<RootOf_Z2+b_Z+c&comma;index=real1Sample Point&equals;c=−1&comma;b=0&comma;x=−2Index&equals;1&comma;1&comma;1&comma;Description&equals;c<0x=RootOf_Z2+b_Z+c&comma;index=real1Sample Point&equals;c=−1&comma;b=0&comma;x=−1Index&equals;1&comma;1&comma;2&comma;Description&equals;c=0b<0x<RootOf_Z_Z+b&comma;index=real1Sample Point&equals;c=0&comma;b=−1&comma;x=−1Index&equals;2&comma;1&comma;1&comma;Description&equals;c=0b<0x=RootOf_Z_Z+b&comma;index=real1Sample Point&equals;c=0&comma;b=−1&comma;x=0Index&equals;2&comma;1&comma;2&comma;Description&equals;c=0b=0x<0Sample Point&equals;c=0&comma;b=0&comma;x=−1Index&equals;2&comma;2&comma;1

(33)
• 

The new GetCells method, which supersedes GetLeafCells, also has additional options to control the output.

r := GetCells(C, output=[samplepoints,descriptions]):

r[1][1..5];

c=−1&comma;b=0&comma;x=−2&comma;c=−1&comma;b=0&comma;x=−1&comma;c=0&comma;b=−1&comma;x=−1&comma;c=0&comma;b=−1&comma;x=0&comma;c=0&comma;b=0&comma;x=−1

(34)

r[2][1..5];

c<0x<RootOf_Z2+b_Z+c&comma;index=real1&comma;c<0x=RootOf_Z2+b_Z+c&comma;index=real1&comma;c=0b<0x<RootOf_Z_Z+b&comma;index=real1&comma;c=0b<0x=RootOf_Z_Z+b&comma;index=real1&comma;c=0b=0x<0

(35)

Various Small Improvements

• 

The ceil, floor, and round functions are 1.5-2x faster for some numeric arguments in Maple 2024.

CodeTools:-Usage([seq(round(n), n=1..10^5)]):

memory used=85.45MiB, alloc change=0 bytes, cpu time=217.00ms, real time=218.00ms, gc time=0ns

CodeTools:-Usage([seq(floor(n/13), n=1..10^5)]):

memory used=191.96MiB, alloc change=0 bytes, cpu time=2.00s, real time=1.25s, gc time=1.05s

• 

The evalhf command uses a more accurate formula for computing the tangent, cotangent, hyperbolic tangent, and hyperbolic cotangent function in certain areas of the complex plane. As a consequence, evalhf is now used for computing these functions numerically in those parts of the complex plane whenever the requested precision is suitable for hardware float computation. This speeds the following computation up by 4-5x.

CodeTools:-Usage([seq(tan(n * 1e-4 + 20.*I), n=1..10^4)]):

memory used=75.71MiB, alloc change=0 bytes, cpu time=811.00ms, real time=811.00ms, gc time=0ns