Opened 12 months ago
Last modified 4 months ago
#30071 new enhancement
speed up Maxima computations by using more of maxima_calculus.eval()
Reported by: | dimpase | Owned by: | |
---|---|---|---|
Priority: | major | Milestone: | sage-9.4 |
Component: | interfaces | Keywords: | |
Cc: | nbruin, rws, kcrisman | Merged in: | |
Authors: | Reviewers: | ||
Report Upstream: | N/A | Work issues: | |
Branch: | Commit: | ||
Dependencies: | Stopgaps: |
Description (last modified by )
Empirically, maxima_calculus.eval()
is 5-7 times faster than maxima.eval()
, cf. e.g.
sage: timeit("L = [(i/100.0, maxima_calculus.eval('jacobi_sn (%s/100.0,2.0)'%i)) for i in range(-300,300)]") 5 loops, best of 3: 110 ms per loop sage: timeit("L = [(i/100.0, maxima.eval('jacobi_sn (%s/100.0,2.0)'%i)) for i in range(-300,300)]") 5 loops, best of 3: 556 ms per loop
For some reason, there are dozens of maxima.eval
calls in sage/[src,doc] - and none of maxima_calculus.eval
. Just going and changing these will be an improvement (in particular, on Cygwin, where pexpect is very flaky, cf #22191).
maxima.jacobi_sn()
is also much slower than
maxima_calculus.jacobi_sn()
This should be a part of #17753.
Change History (13)
comment:1 Changed 12 months ago by
- Description modified (diff)
- Summary changed from speed up Maxima computations by using more of maxima_lib to speed up Maxima computations by using more of maxima_calculus.eval()
comment:2 Changed 12 months ago by
comment:3 follow-up: ↓ 4 Changed 12 months ago by
Testing on macOS, I get
%timeit maxima_calculus.jacobi_sn(0.1,2.0) 1000 loops, best of 5: 484 µs per loop sage: %timeit maxima.jacobi_sn(0.1,2.0) 100 loops, best of 5: 1.98 ms per loop
comment:4 in reply to: ↑ 3 Changed 12 months ago by
- Description modified (diff)
Replying to mkoeppe:
Testing on macOS, I get
%timeit maxima_calculus.jacobi_sn(0.1,2.0) 1000 loops, best of 5: 484 µs per loop sage: %timeit maxima.jacobi_sn(0.1,2.0) 100 loops, best of 5: 1.98 ms per loop
right, I probably did something wrong here. Indeed, on Linux I get similar timings.
comment:5 follow-up: ↓ 6 Changed 12 months ago by
still there is something funny going on
sage: timeit("L = [(i/100.0, maxima_calculus.jacobi_sn(i/100.0,2.0)) for i in range(-300,300)]") 5 loops, best of 3: 612 ms per loop sage: timeit("L = [(i/100.0, maxima_calculus.eval('jacobi_sn (%s/100.0,2.0)'%i)) for i in range(-300,300)]") 5 loops, best of 3: 89.3 ms per loop
If I remove _calculus
above, the first line errors out with TIMEOUT: Timeout exceeded.
.
comment:6 in reply to: ↑ 5 Changed 12 months ago by
Replying to dimpase:
still there is something funny going on
sage: timeit("L = [(i/100.0, maxima_calculus.jacobi_sn(i/100.0,2.0)) for i in range(-300,300)]") 5 loops, best of 3: 612 ms per loop sage: timeit("L = [(i/100.0, maxima_calculus.eval('jacobi_sn (%s/100.0,2.0)'%i)) for i in range(-300,300)]") 5 loops, best of 3: 89.3 ms per loop
I think this example is showing that maxima's string parser is faster than our to/from binary data conversion for ecllib. I can believe that: there's still a lot of work and memory allocation to do to translate python objects to lisp objects and back. I can imagine that parsing such a small string is easier (the construction of the lisp float objects etc. needs to happen in both cases, so it's really just parsing against the python object constructions). You could try and profile the code to see if anything bad is happening.
For the results via the expect interface: since the python-to-maxima translation now needs to happen through parsing anyway, it's bound to be slower: there's no upside compared to the "eval" at all. The fact that it actually times out: I'd suspect there's an io buffer that gets flooded or an expect interface that gets out of sync due to the high data flow. Note that the timeout happens in the expect interface.
comment:7 Changed 12 months ago by
In src/sage/calculus/calculus.py one reads
The symbolic calculus package uses its own copy of Maxima for simplification, etc., which is separate from the default system-wide version:: sage: maxima.eval('[x,y]: [1,2]') '[1,2]' sage: maxima.eval('expand((x+y)^3)') '27' If the copy of maxima used by the symbolic calculus package were the same as the default one, then the following would return 27, which would be very confusing indeed! :: sage: x, y = var('x,y') sage: expand((x+y)^3) x^3 + 3*x^2*y + 3*x*y^2 + y^3
Is this the only issue (variable binding in SR done via maxima
, not maxima_lib
) that
prevents Sage from fully switching to maxima_lib
backend?
comment:8 follow-up: ↓ 9 Changed 12 months ago by
For some reason, there are dozens of maxima.eval calls in sage/[src,doc]
Note that at least in some modules, actually lazy_import('sage.interfaces.maxima_lib','maxima')
is done.
comment:9 in reply to: ↑ 8 Changed 12 months ago by
comment:10 Changed 12 months ago by
Also the code of sage/symbolic/expression.pyx
(but not doctests) use from sage.calculus.calculus import maxima
. Likewise other modules in sage/symbolic
Let's make a list... Outside of doctests, I see:
combinat/combinat.py: from sage.interfaces.all import maxima
Anything else?
comment:11 Changed 12 months ago by
in src/doc - the example in the ticket description is from there
comment:12 Changed 10 months ago by
- Milestone changed from sage-9.2 to sage-9.3
comment:13 Changed 4 months ago by
- Milestone changed from sage-9.3 to sage-9.4
Setting new milestone based on a cursory review of ticket status, priority, and last modification date.
I really want to understand why
maxima_calculus.foo()
is as slow asmaxima.foo()
- this look more like a bug than anything else.I can't seem to find the code responsible for this, though.