Skip to content

Vectorize lazy - #985

Open
matteobachetti wants to merge 8 commits into
mainfrom
vectorize_lazy
Open

matteobachetti wants to merge 8 commits into
mainfrom
vectorize_lazy

Conversation

@matteobachetti

Copy link
Copy Markdown
Member

Importing Stingray was slow because the Numba @vectorize functions in stats.py and fourier.py listed their signatures, so they were compiled again at every import, which took about 1.6 s.

This PR adds stingray.utils.lazy_vectorize, which compiles a fixed list of signatures the first time a function is called (from Python or from Numba-compiled code), caches them on disk, and then compiles nothing else.

Simply dropping the signatures would not have been safe: Numba then compiles a loop for each new combination of input types, and after a call with float32 and float64 arrays, a float64 array combined with a Python float could be computed in float32. Each function now has a single float64 signature, so float32 inputs are computed in float64 (with or without Numba), a number of trials ≥ 2³¹ no longer raises OverflowError, and import stingray drops from 3.0 s to 1.4 s, at the cost of about 0.1 s the first time these functions are called.

Disclosure: I investigated the slow loading of stingray with Claude, this is work I've done with its assistance. I verified each step and decided the tradeoffs (e.g. fewer function signatures for faster loading).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Address the fixed-signature initialization, thread-safety, and Numba compatibility concerns.

Get a fresh assessment by requesting another Copilot review.

Pull request overview

This pull request adds lazy Numba vectorization to reduce import time while preserving fixed-signature precision.

Changes:

  • Adds deferred compilation and caching via lazy_vectorize.
  • Migrates statistics and Fourier helpers.
  • Adds regression tests and changelog entries.
File summaries
File Summary
stingray/utils.py Implements lazy vectorization.
stingray/tests/test_utils.py Tests lazy compilation behavior.
stingray/tests/test_stats.py Tests precision and large trial counts.
stingray/tests/test_fourier.py Tests complex precision handling.
stingray/stats.py Applies lazy vectorization to statistics helpers.
stingray/fourier.py Applies lazy vectorization to Fourier helpers.
docs/changes/985.feature.rst Documents import-time performance improvements.
docs/changes/985.bugfix.rst Documents precision and overflow fixes.
Review details

Suppressed comments (2)

stingray/utils.py:141

  • An empty signature list is treated as the "not compiled yet" sentinel here. With signatures=[], _compile_for_args falls through to DUFunc's dynamic compilation, so later input-type combinations can add loops instead of being rejected, contradicting the fixed-signature contract. Reject an empty list during initialization (or use a separate initialization flag).
            signatures = getattr(self, "_lazy_signatures", None)
            if not signatures:
                return False

stingray/utils.py:115

  • These imports depend on Numba's private numba.core/numba.np modules, while numba is an unpinned optional dependency in pyproject.toml. A Numba release that moves either symbol will make importing stingray.utils fail before the HAS_NUMBA fallback can run; please constrain the supported Numba range or add a compatibility path that preserves the optional-dependency fallback.
    from numba.core import sigutils
    from numba.np.numpy_support import ufunc_find_matching_loop
    from numba.np.ufunc.dufunc import DUFunc
  • Files reviewed: 8/8 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread stingray/utils.py
…first call, for fixed float32 and float64 signatures
…ctions, so that float32 inputs are computed in float64 and the first call compiles less
…vectorize, and explain why each new test is needed
…nsupported types, and when pickled; exclude its unreachable fallback from coverage
…piler lock, so that concurrent first calls are safe
@codecov

codecov Bot commented Oct 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.74%. Comparing base (f965a0f) to head (a272d77).
⚠️ Report is 9 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #985      +/-   ##
==========================================
+ Coverage   96.69%   96.74%   +0.05%     
==========================================
  Files          48       48              
  Lines       11219    11266      +47     
==========================================
+ Hits        10848    10899      +51     
+ Misses        371      367       -4     
Files with missing lines Coverage Δ
stingray/fourier.py 100.00% <100.00%> (ø)
stingray/stats.py 99.55% <100.00%> (ø)
stingray/utils.py 99.15% <100.00%> (+0.08%) ⬆️

... and 4 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 83008ff...a272d77. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants