Skip to content

Improve fitting performance of most non-linear fitters - #16673

Merged
nden merged 4 commits into
astropy:mainfrom
astrofrog:improve-modeling-performance
Aug 10, 2024
Merged

nden merged 4 commits into
astropy:mainfrom
astrofrog:improve-modeling-performance

Conversation

@Cadair

@Cadair Cadair commented Jul 4, 2024 •

Copy link
Copy Markdown
Member

This PR significantly speeds up fitting of models for most of the non-linear fitters. When profiling this, we found that a lot of the overhead was in the fact that the fitters evaluate the model using call, which includes several time-consuming pre- and post-evaluation steps. However, in the non-linear fitters, the models always have scalar parameters and we have control over the inputs to the models, so these checks are unnecessary. We can therefore call Model.evaluate directly which speeds things up a lot. For compound models, this can speed up the fitting by factors of 4x or more.

For a simple 1D Gaussian unconstrained fit:

Fit example
import time
import numpy as np
from astropy.modeling.models import Gaussian1D
from astropy.modeling.fitting import TRFLSQFitter

g = Gaussian1D()
fitter = TRFLSQFitter()

np.random.seed(12345)

x = np.linspace(-10, 10, 100)
y = np.exp(-(x - 1.1) ** 2 / 3) + np.random.uniform(-0.2, 0.2, 100)

start = time.time()
for iter in range(1000):
    g_fit = fitter(g, x, y)
end = time.time()

print(f"{end-start}")

This takes the run time for me from 3.02s on main to 2.19s on this PR.

With use_min_max_constraints and bounds set it goes from 3.64s to 2.2s.

If you change the model being fit to g = Gaussian1D() + Gaussian1D() then it takes 27.9s on main and 9.4s on this PR.

  • By checking this box, the PR author has requested that maintainers do NOT use the "Squash and Merge" button. Maintainers should respect this when possible; however, the final decision is at the discretion of the maintainer that merges the PR.

@Cadair Cadair added modeling Performance benchmark Run benchmarks for a PR labels Jul 4, 2024
@github-actions

github-actions Bot commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

Thank you for your contribution to Astropy! 🌌 This checklist is meant to remind the package maintainers who will review this pull request of some common things to look for.

  • Do the proposed changes actually accomplish desired goals?
  • Do the proposed changes follow the Astropy coding guidelines?
  • Are tests added/updated as required? If so, do they follow the Astropy testing guidelines?
  • Are docs added/updated as required? If so, do they follow the Astropy documentation guidelines?
  • Is rebase and/or squash necessary? If so, please provide the author with appropriate instructions. Also see instructions for rebase and squash.
  • Did the CI pass? If no, are the failures related? If you need to run daily and weekly cron jobs as part of the PR, please apply the "Extra CI" label. Codestyle issues can be fixed by the bot.
  • Is a change log needed? If yes, did the change log check pass? If no, add the "no-changelog-entry-needed" label. If this is a manual backport, use the "skip-changelog-checks" label unless special changelog handling is necessary.
  • Is this a big PR that makes a "What's new?" entry worthwhile and if so, is (1) a "what's new" entry included in this PR and (2) the "whatsnew-needed" label applied?
  • At the time of adding the milestone, if the milestone set requires a backport to release branch(es), apply the appropriate "backport-X.Y.x" label(s) before merge.

@github-actions

github-actions Bot commented Jul 4, 2024

Copy link
Copy Markdown
Contributor

👋 Thank you for your draft pull request! Do you know that you can use [ci skip] or [skip ci] in your commit messages to skip running continuous integration tests until you are ready?

@Cadair
Cadair force-pushed the improve-modeling-performance branch 2 times, most recently from f9855e9 to f7cd5ec Compare July 4, 2024 13:39
@Cadair

Cadair commented Jul 4, 2024

Copy link
Copy Markdown
Member Author

The test fails are due to #16675

@astrofrog

Copy link
Copy Markdown
Member

I've split out some of the changes here that relate to the Model API into #16677

@pllim pllim added this to the v7.0.0 milestone Jul 5, 2024
@Cadair
Cadair force-pushed the improve-modeling-performance branch 2 times, most recently from b98648e to 65c65c7 Compare July 10, 2024 15:43
@Cadair
Cadair marked this pull request as ready for review July 10, 2024 15:44
@Cadair
Cadair requested a review from a team as a code owner July 10, 2024 15:44
Comment thread docs/changes/modeling/16673.feature.rst
@pllim

pllim commented Jul 11, 2024

Copy link
Copy Markdown
Member

Please use the new perf change log category, see:

@astrofrog

Copy link
Copy Markdown
Member

@pllim already done :)

@pllim

pllim commented Jul 11, 2024

Copy link
Copy Markdown
Member

I think you need to rebase because the bot does not know about "perf" here.

@Cadair
Cadair force-pushed the improve-modeling-performance branch from f02719c to 390780d Compare July 11, 2024 15:34
@Cadair

Cadair commented Jul 11, 2024

Copy link
Copy Markdown
Member Author

My kingdom for that update and rebase button on the github web ui

@astrofrog

Copy link
Copy Markdown
Member

The asv benchmarks seem to be working! The one regression is a fluke.

@astrofrog

astrofrog commented Jul 15, 2024 •

Copy link
Copy Markdown
Member

For convenience:

2024-07-11T16:08:05.5964106Z | Change   | Before [ff59e9cf]    | After [2a05840e]    |   Ratio | Benchmark (Parameter)                                         |
2024-07-11T16:08:05.5966580Z |----------|----------------------|---------------------|---------|---------------------------------------------------------------|
2024-07-11T16:08:05.5968188Z | -        | 103±3ms              | 63.2±0.3ms          |    0.61 | modeling.fitting.time_datafit_compound_LevMarLSQFitter        |
2024-07-11T16:08:05.5972159Z | -        | 2.17±0.03ms          | 968±7μs             |    0.45 | modeling.fitting.time_Gaussian1D_LevMarLSQFitter              |
2024-07-11T16:08:05.5973944Z | -        | 368±60μs             | 162±3μs             |    0.44 | units.time_quantity_array_conversion                          |
2024-07-11T16:08:05.5975459Z | -        | 289±70μs             | 92.4±0.7μs          |    0.32 | units.time_quantity_init_array                                |
2024-07-11T16:08:05.5977071Z | -        | 260±2ms              | 64.9±0.3ms          |    0.25 | modeling.fitting.time_large_gauss_combined_1d_LevMarLSQFitter |
2024-07-11T16:08:05.5978602Z | -        | 19.9±4ms             | 4.22±0.02ms         |    0.21 | modeling.fitting.time_combined_gauss_1d_LevMarLSQFitter       |
2024-07-11T16:08:05.5980178Z | -        | 176±30μs             | 35.8±0.2μs          |    0.2  | units.time_quantity_creation                                  |
2024-07-11T16:08:05.5981557Z | Change   | Before [ff59e9cf]    | After [2a05840e]    |   Ratio | Benchmark (Parameter)          |
2024-07-11T16:08:05.5982920Z |----------|----------------------|---------------------|---------|--------------------------------|
2024-07-11T16:08:05.5984049Z | +        | 41.8±0.1μs           | 83.2±40μs           |    1.99 | units.time_quantity_times_unit |
2024-07-11T16:08:05.5985127Z 
2024-07-11T16:08:05.5985548Z SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.

@astrofrog

Copy link
Copy Markdown
Member

The fitting results are all genuine and reliable (they are on the >1ms level). Not sure what's up with the units results but they are on the microsecond level so maybe just can't measure that in CI?

@nden nden 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.

LGTM

@pllim

pllim commented Aug 10, 2024

Copy link
Copy Markdown
Member

Does this comment need to be resolved? 👉 #16673 (comment)

@astrofrog

astrofrog commented Aug 10, 2024 •

Copy link
Copy Markdown
Member

No I was just commenting that the units asv tests were unreliable but not related to the changes here. This is good to go.

@nden
nden merged commit f788114 into astropy:main Aug 10, 2024
@mcara

mcara commented Sep 9, 2024 •

Copy link
Copy Markdown
Contributor

This PR is breaking code that relies on documented behavior, specifically: https://docs.astropy.org/en/stable/api/astropy.modeling.fitting.LevMarLSQFitter.html#astropy.modeling.fitting.LevMarLSQFitter.objective_function

It introduces additional parameters to args that are not expected. This is a change in API (maybe not formally but still, changing arguments provided to a callback has similar effects).

@pllim

pllim commented Sep 10, 2024 •

Copy link
Copy Markdown
Member

Oh no! We should either

  1. address the API change and document it, or
  2. revert this PR, see Revert "Improve fitting performance of most non-linear fitters" #16979

@astrofrog

astrofrog commented Sep 10, 2024 •

Copy link
Copy Markdown
Member

I have an idea to fix this, can take a look this morning unless @Cadair beats me to it.

@neutrinoceros

Copy link
Copy Markdown
Contributor

Thanks for the heads up @astrofrog ! I was about to give it a try myself, glad we could avoid another race condition :)

@pllim

pllim commented Sep 10, 2024

Copy link
Copy Markdown
Member

Is #16982 @Cadair beating @astrofrog to it?

@Cadair

Cadair commented Sep 10, 2024

Copy link
Copy Markdown
Member Author

Yes

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants