Skip to content

Speed up Thiele continuum approximation; pluggable evaluation strategy - #35

Merged
tobydriscoll merged 6 commits into
mainfrom
evaluate-scratch-buffers
Jun 22, 2026
Merged

Speed up Thiele continuum approximation; pluggable evaluation strategy#35
tobydriscoll merged 6 commits into
mainfrom
evaluate-scratch-buffers

Conversation

@tobydriscoll

Copy link
Copy Markdown
Member

Summary

Memory- and type-stability work on the Thiele continuum approximate path, plus a cleaner mechanism for selecting evaluation strategies. All 925 tests pass; no behavioral changes to results (the two recurrences agree to ~1e-15).

Performance (vs. main, median via benchmark/compare.jl)

benchmark change
Thiele continuum exp_interval / tanh_steep / abs_circle −62% / −72% / −53%
Barycentric continuum exp_interval / tanh_steep / abs_circle −21% / −10% / −6%
thiele_vector (scalar r.(z)) −23% (3010 → 3 allocations)
poles −5%
discrete approximate, bary_vector invariant

What changed

  • evaluate! scratch reuse: new evaluate!(t, r, z, a, b) overload lets the hot loop reuse the recurrence's work arrays instead of allocating per call; the 3-arg form delegates to it.
  • Allocation-light index management: the live test-point set is tracked as a linear integer index vector (active), grown incrementally and rebuilt only on path reset, supporting a non-rectangular active set. Test points are gathered into a dense reusable buffer so evaluate! runs on contiguous vectors.
  • Function barriers (_sweep!): the per-point work is routed through a single barrier function (two methods) so it specializes on concrete element types. This is necessary because ComplexRegions' point(d, ·) infers as Any, making σ///buffers abstract inside approximate.
  • DiscretizedPath.points parameterized (Matrix{P}) — fixes an abstract field type and benefits all consumers (Barycentric, parfrac, spacing, collect).
  • Evaluation-strategy mechanism: replaced the non-const-global _evaluator/_new_weight toggles (which forced a dynamic dispatch + heap box on every scalar evaluation) with strategy singletons OneDiv/Classic <: ThieleMethod. The default path is now a static, allocation-free call; evaluate(r, z, method) / add_node!(r, z, y, method) take an optional explicit strategy, and set_eval_method / set_weight_method retain the global-switch capability for tests.

API additions (exported)

ThieleMethod, OneDiv, Classic, set_eval_method, set_weight_method.

Housekeeping

  • Version bumped to 0.3.7.
  • Tightened ComplexRegions compat to 0.3.9 (earlier 0.3 allowed 0.3.7, which lacks points used by the Barycentric path).
  • Added benchmark/compare.jl, a before/after benchmark harness.

@codecov

codecov Bot commented Jun 22, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.36620% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/thiele.jl 94.28% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Ratios above 1 mean this PR is slower than main.

main 12e9781... main / 12e9781...
approximate/aaa/abs_circle 0.0451 ± 0.0021 s 0.0448 ± 0.0026 s 1.01 ± 0.075
approximate/aaa/exp_interval 0.114 ± 0.027 ms 0.0998 ± 0.025 ms 1.15 ± 0.39
approximate/aaa/tanh_steep 1.21 ± 0.055 ms 1.12 ± 0.068 ms 1.08 ± 0.082
approximate/thiele/abs_circle 9.23 ± 0.35 ms 3.35 ± 0.1 ms 2.76 ± 0.13
approximate/thiele/exp_interval 0.175 ± 0.022 ms 0.0659 ± 0.0055 ms 2.65 ± 0.4
approximate/thiele/tanh_steep 0.694 ± 0.027 ms 0.166 ± 0.013 ms 4.18 ± 0.36
approximate_discrete/aaa/abs_shift 3.37 ± 0.26 ms 3.41 ± 0.36 ms 0.988 ± 0.13
approximate_discrete/aaa/sin_recip 0.882 ± 0.11 ms 0.881 ± 0.13 ms 1 ± 0.19
approximate_discrete/aaa/tanh_steep 12.1 ± 0.61 ms 12.2 ± 0.98 ms 0.995 ± 0.095
approximate_discrete/thiele/abs_shift 0.206 ± 0.016 ms 0.206 ± 0.016 ms 1 ± 0.11
approximate_discrete/thiele/sin_recip 0.12 ± 0.0082 ms 0.119 ± 0.008 ms 1 ± 0.097
approximate_discrete/thiele/tanh_steep 0.626 ± 0.026 ms 0.623 ± 0.023 ms 1 ± 0.056
evaluate/bary_vector 0.0872 ± 0.004 ms 0.0876 ± 0.0046 ms 0.995 ± 0.069
evaluate/thiele_vector 0.0847 ± 0.0041 ms 0.0584 ± 0.00077 ms 1.45 ± 0.073
poles/thiele 0.356 ± 0.011 ms 0.354 ± 0.011 ms 1.01 ± 0.044
time_to_load 0.66 ± 0.0052 s 0.667 ± 0.0021 s 0.989 ± 0.0084

Benchmark Plots

Plots have been uploaded as an artifact to this workflow run
("Actions" -> this run -> "Artifacts" at the bottom).

@tobydriscoll
tobydriscoll merged commit 92041dc into main Jun 22, 2026
6 checks passed
@tobydriscoll

Copy link
Copy Markdown
Member Author

@JuliaRegistrator register

Release notes:

  • Improved Thiele construction speed by eliminating type instabilities and dynamic dispatches.
  • Changed and exposed the undocumented mechanism for switching Thiele evaluation methods.

@JuliaRegistrator

Copy link
Copy Markdown

Comments on pull requests will not trigger Registrator, as it is disabled. Please try commenting on a commit or issue.

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