-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Closed
Labels
Milestone
Description
See #19199.
I've used asv
to bisect a significant slowdown in the cholesky_solve
benchmark:
$ asv find sympy-1.5.1..master solve.TimeMatrixSolve2.time_cholesky_solve
...
· Greatest regression found: a8a3a3b0 <pull/18576/head~1>
That has bisected to commit a8a3a3b from #18564.
The benchmark can be tested easily with
# t.py
import sympy
from sympy import *
n = 3
A = sympy.Matrix(n, n, lambda i, j: sympy.Symbol('a{}{}'.format(i, j)))
b = sympy.Matrix(n, 1, lambda i, j: sympy.Symbol('b{}{}'.format(i, j)))
A_sym = sympy.Matrix(n, n, lambda i, j:
sympy.Symbol('a{}{}'.format(*sorted((i, j)))))
def time_cholesky_solve():
A_sym.cholesky_solve(b)
# pprint(A_sym.cholesky_solve(b))
That matrix is:
In [2]: A_sym
Out[2]:
⎡a₀₀ a₀₁ a₀₂⎤
⎢ ⎥
⎢a₀₁ a₁₁ a₁₂⎥
⎢ ⎥
⎣a₀₂ a₁₂ a₂₂⎦
In [3]: b
Out[3]:
⎡b₀₀⎤
⎢ ⎥
⎢b₁₀⎥
⎢ ⎥
⎣b₂₀⎦
Both master and 1.5.1 give complicated results but on 1.5.1 it takes roughly a millisecond whereas on master it takes a couple of seconds:
$ git checkout master
$ python -m timeit -s 'from t import time_cholesky_solve' 'time_cholesky_solve()'
1 loop, best of 5: 2.36 sec per loop
$ git checkout sympy-1.5.1
$ python -m timeit -s 'from t import time_cholesky_solve' 'time_cholesky_solve()'
1 loop, best of 5: 1.61 msec per loop
Running cProfile gives:
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
58 0.004 0.000 9.004 0.155 __init__.py:1(<module>)
749/1 0.019 0.000 8.908 8.908 {built-in method builtins.exec}
1 0.000 0.000 8.908 8.908 t.py:1(<module>)
1 0.000 0.000 6.444 6.444 matrices.py:2198(cholesky_solve)
1 0.000 0.000 6.444 6.444 solvers.py:204(_cholesky_solve)
1 0.000 0.000 6.149 6.149 matrices.py:390(is_positive_definite)
1 0.000 0.000 6.149 6.149 eigen.py:675(_is_positive_definite)
2/1 0.000 0.000 6.149 6.149 matrices.py:367(_eval_is_positive_definite)
2/1 0.000 0.000 6.149 6.149 eigen.py:623(_eval_is_positive_definite)
1 0.000 0.000 5.236 5.236 matrices.py:370(eigenvals)
1 0.000 0.000 5.236 5.236 eigen.py:80(_eigenvals)
579/3 0.006 0.000 3.203 1.068 <frozen importlib._bootstrap>:986(_find_and_load)
579/3 0.004 0.000 3.202 1.067 <frozen importlib._bootstrap>:956(_find_and_load_unlocked)
556/3 0.004 0.000 3.202 1.067 <frozen importlib._bootstrap>:650(_load_unlocked)
528/3 0.006 0.000 3.202 1.067 <frozen importlib._bootstrap_external>:777(exec_module)
979/5 0.001 0.000 3.199 0.640 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
750 0.001 0.000 2.983 0.004 densearith.py:1609(dmp_div)
9537/750 0.065 0.000 2.981 0.004 densearith.py:1358(dmp_rr_div)
1 0.000 0.000 2.968 2.968 polyroots.py:788(roots)
465/61 0.002 0.000 2.870 0.047 euclidtools.py:1561(dmp_inner_gcd)
714 0.001 0.000 2.839 0.004 densearith.py:1654(dmp_quo)
414/61 0.001 0.000 2.833 0.046 euclidtools.py:1525(_dmp_inner_gcd)
429/61 0.001 0.000 2.833 0.046 euclidtools.py:1269(dmp_zz_heu_gcd)
429/61 0.001 0.000 2.833 0.046 euclidtools.py:891(_dmp_rr_trivial_gcd)
306/19 0.002 0.000 2.832 0.149 euclidtools.py:938(_dmp_simplify_gcd)
115/40 0.002 0.000 2.785 0.070 simplify.py:395(simplify)
1 0.000 0.000 2.264 2.264 matrices.py:114(charpoly)
1 0.000 0.000 2.264 2.264 determinant.py:329(_charpoly)
60 0.001 0.000 2.234 0.037 polytools.py:6610(cancel)
It looks like the time is spent computing the eigenvalues in is_positive_definite
.