Skip to content

Conversation

@Fyrebright
Copy link
Contributor

@Fyrebright Fyrebright commented Jun 19, 2025

  • Now skips 2D checks in perform
  • Updated the default arguments for check_finite to false to match documentation
  • Add benchmark test case

Description

Adds _cholesky method to slinalg.Cholesky to replace the scipy.linalg.cholesky wrapper. It is almost identical to the corresponding scipy function but it skips the 2d check and the batching wrapper.

Previous performance (with check_finite=False):

benchmark: 5.1.0 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000) --------------------------------------------------- benchmark: 1 tests --------------------------------------------------- Name (time in us) Min Max Mean StdDev Median IQR Outliers OPS (Kops/s) Rounds Iterations -------------------------------------------------------------------------------------------------------------------------- test_cholesky_performance 5.6610 43.2910 6.8433 2.4983 5.9610 0.1810 1312;1574 146.1280 9487 1 -------------------------------------------------------------------------------------------------------------------------- 

After changes:

benchmark: 5.1.0 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000) --------------------------------------------------- benchmark: 1 tests -------------------------------------------------- Name (time in us) Min Max Mean StdDev Median IQR Outliers OPS (Kops/s) Rounds Iterations ------------------------------------------------------------------------------------------------------------------------- test_cholesky_performance 5.1500 28.5640 5.5494 1.0101 5.4210 0.1100 262;628 180.2012 12753 1 ------------------------------------------------------------------------------------------------------------------------- 

Related Issue

Checklist

Type of change

  • New feature / enhancement
  • Bug fix
  • Documentation
  • Maintenance
  • Other (please specify): performance

📚 Documentation preview 📚: https://pytensor--1487.org.readthedocs.build/en/1487/

* Now skips 2D checks in perform * Updated the default arguments for `check_finite` to false to match documentation * Add benchmark test case
@Fyrebright Fyrebright marked this pull request as ready for review June 19, 2025 22:09
Copy link
Member

@ricardoV94 ricardoV94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice start, left some comments

@Fyrebright
Copy link
Contributor Author

Thank you for the feedback. I moved it all to perform and removed the asarray,_datacopied checks. I also moved the empty input case to the beginning and added test coverage for it.

Copy link
Member

@jessegrabowski jessegrabowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking really great! I see a few more places we can improve the performance (avoiding copy + cleaning up the code) then I think it'll be ready to merge

@jessegrabowski
Copy link
Member

Looks really nice! I triggered a CI run, waiting to see if tests pass then will approve, pending thumbs up from @ricardoV94

@jessegrabowski
Copy link
Member

jessegrabowski commented Jun 22, 2025

You have a test failure in tests/link/numba/test_slinalg.py::test_cholesky_raises_on_nan_input:

2025-06-21T21:14:33.0385589Z =================================== FAILURES =================================== 2025-06-21T21:14:33.0386251Z ______________________ test_cholesky_raises_on_nan_input _______________________ 2025-06-21T21:14:33.0386688Z 2025-06-21T21:14:33.0386858Z def test_cholesky_raises_on_nan_input(): 2025-06-21T21:14:33.0387381Z test_value = rng.random(size=(3, 3)).astype(floatX) 2025-06-21T21:14:33.0387886Z test_value[0, 0] = np.nan 2025-06-21T21:14:33.0388256Z 2025-06-21T21:14:33.0388568Z x = pt.tensor(dtype=floatX, shape=(3, 3)) 2025-06-21T21:14:33.0389299Z x = x.T.dot(x) 2025-06-21T21:14:33.0389718Z g = pt.linalg.cholesky(x) 2025-06-21T21:14:33.0390184Z f = pytensor.function([x], g, mode="NUMBA") 2025-06-21T21:14:33.0390622Z 2025-06-21T21:14:33.0391099Z > with pytest.raises(np.linalg.LinAlgError, match=r"Non-numeric values"): 2025-06-21T21:14:33.0391737Z ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 2025-06-21T21:14:33.0392394Z E Failed: DID NOT RAISE <class 'numpy.linalg.LinAlgError'> 2025-06-21T21:14:33.0392804Z 2025-06-21T21:14:33.0392979Z tests/link/numba/test_slinalg.py:471: Failed 

Could be related to the change in the default check_finite flag? You might need to adjust this test to correctly set the flag if so.

Copy link
Member

@ricardoV94 ricardoV94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. small comment


if self.check_finite and not np.isfinite(x).all():
if self.on_error == "nan":
out[0] = np.full(x.shape, np.nan, dtype=node.outputs[0].type.dtype)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
out[0] = np.full(x.shape, np.nan, dtype=node.outputs[0].type.dtype)
out[0] = np.full(x.shape, np.nan, dtype=potrf.dtype)
@Fyrebright
Copy link
Contributor Author

Could be related to the change in the default check_finite flag? You might need to adjust this test to correctly set the flag if so.

It is fixed now. I had been skipping the link/* tests until now. They are all passing on my machine except for:

FAILED tests/scan/test_basic.py::test_cython_performance - ModuleNotFoundError: No module named 'pytensor.scan.scan_perform' FAILED tests/scan/test_basic.py::test_output_storage_reuse[cvm] - ModuleNotFoundError: No module named 'pytensor.scan.scan_perform' 
@codecov
Copy link

codecov bot commented Jun 23, 2025

Codecov Report

❌ Patch coverage is 70.37037% with 8 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (main@d3bbc20). Learn more about missing BASE report.
⚠️ Report is 138 commits behind head on main.

Files with missing lines Patch % Lines
pytensor/tensor/slinalg.py 70.37% 5 Missing and 3 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@ Coverage Diff @@ ## main #1487 +/- ## ======================================= Coverage ? 81.98% ======================================= Files ? 231 Lines ? 52192 Branches ? 9185 ======================================= Hits ? 42790 Misses ? 7094 Partials ? 2308 
Files with missing lines Coverage Δ
pytensor/tensor/slinalg.py 92.19% <70.37%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
Copy link
Member

@jessegrabowski jessegrabowski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks for this!

@jessegrabowski jessegrabowski merged commit 236e50d into pymc-devs:main Jun 23, 2025
73 of 74 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment