Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoiding unnecessary setup operations #503

Merged
merged 8 commits into from
Jan 18, 2024
Merged

Conversation

christophe-david
Copy link
Contributor

@christophe-david christophe-david commented Jan 15, 2024

This PR fixes some performance problems of FAST-OAD.

To get knowledge of the structure of OpenMDAO problems, a setup operation is needed. Until now, due to the several changes that were done separately, this setup operation was done almost each time information was needed, which proved to be CPU costly.

Here the problem analysis is done in only one place, which allows to reduce to the minimum the number of setup calls. There is still one "additional" setup operation needed to analyze the problem, and possibly another one if dynamically shaped variables are inputs of the problem.

Also, write_needed_inputs implementation has been put back in FASTOADPoblem (while keeping the FASTOADProblemConfigurator method), which allows to spare 2 setup calls when called on the problem instance that will do the computation (when done from FASTOADProblemConfigurator, it is done on a separate instance).

As a result, the integration test test_oad_process uses now 2 setup calls, instead of 10 previously.

christophe-david and others added 5 commits January 15, 2024 09:15
Needed problem information are now collected in one step to avoid unneeded setup operations.
write_needed_inputs() back in FASTOADProblem

When not using high-level API, it will allow to have problem analysis done once when doing write_needed_inputs() and not in subsequent operations.
@christophe-david christophe-david changed the title Setup optimisation Avoiding unnecessary setup operations Jan 15, 2024
Copy link

codecov bot commented Jan 15, 2024

Codecov Report

Attention: 3 lines in your changes are missing coverage. Please review.

Comparison is base (15b04af) 84.16% compared to head (4eeb488) 84.24%.
Report is 1 commits behind head on master.

Files Patch % Lines
src/fastoad/io/configuration/configuration.py 50.00% 1 Missing and 1 partial ⚠️
src/fastoad/openmdao/problem.py 98.71% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #503      +/-   ##
==========================================
+ Coverage   84.16%   84.24%   +0.08%     
==========================================
  Files         132      132              
  Lines        6061     6081      +20     
  Branches      891      896       +5     
==========================================
+ Hits         5101     5123      +22     
+ Misses        804      803       -1     
+ Partials      156      155       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@christophe-david christophe-david marked this pull request as ready for review January 15, 2024 10:21
Copy link
Contributor

@florentLutz florentLutz left a comment

Choose a reason for hiding this comment

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

A lot of comments but nothing that prevents the merging of this PR, just a few questions about how things are done 😄

Comment on lines 114 to 115
problem = FASTOADProblem()
self._build_model(problem)
Copy link
Contributor

Choose a reason for hiding this comment

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

It is not a change in the PR but I'm wondering here if this line means that we rebuild the problem each time we call the get_problem method. For instance if we were to keep calling the write_needed_inputs from the FASTOADProblemConfigurator class we would construct the problem twice.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Indeed, the problem is built each time get_problem is called. I think it's better like this because:

  • if a user called get_problem, he is able to keep the generated instance, and I think he has no reason to call get_problem again unless he wants a fresh new instance.
  • we could imagine a case where the configuration is read, get_problem is called, then the configuration is programmatically modified (e.g. optimization definition) and get_problem is called again. In such case, a fresh new instance is really better.

This is why write_needed_inputs implementation has been moved to the FASTOADProblem class, which allows doing this operation on the instance that will be used for the computation.


A deepcopy operation may crash if problem.comm is not pickle-able, like a
def get_problem_copy_without_mpi(problem: T) -> T:
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure about the name of the function. From the description, I seem to understand that this function allows to avoid the problem with MPI by removing the non-pickable object beforehand and readding it afterwards, which would work regardless of whether the problem has MPI or not. So the wihout_mpi seems more like a mpi_safe ?

Copy link
Contributor Author

@christophe-david christophe-david Jan 17, 2024

Choose a reason for hiding this comment

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

Good point. Name adopted in 9bba940.

self.model.add_subsystem(SHAPER_SYSTEM_NAME, ivc, promotes=["*"])
self.self_analysis()

self._analysis.fills_dynamically_shaped_inputs(self)
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't this line already ran when you do a ProblemAnalysis ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had hesitated making a property for that, that would control the running of the analysis at the first usage.

Your question made me decide it was the way to go. Modification done in 4eeb488.

}
)
return dynamic_vars
self.model.set_order([subsystem_name] + self._analysis.subsystem_order)
Copy link
Contributor

Choose a reason for hiding this comment

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

Again not linked with this PR, but do we need to reorder the subsystems ? Isn't naturaly done when we add the models ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A sure thing is that the component are added in the order of the add_subsystem calls.

The fact is that removing this line makes 2 tests fail (these tests do optimization on the Sellar problem).
Other tests (unit and integration) still work fine.
For the record, with the last OpenMDAO version installed, using self.model.options["auto_order"] = True makes the 2 tests work again.

Actually, the 2 tests fail (give incorrect results) because there is no solver at the Problem.model level. Indeed, with an IVC in last position, a loop is needed to have the IVC output correctly fill the needed inputs.

christophe-david and others added 3 commits January 17, 2024 16:02
It will avoid any question about when calling the analysis method. The analysis will be done the first time the property will be used.
Copy link
Contributor

@florentLutz florentLutz left a comment

Choose a reason for hiding this comment

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

No more comments, thanks for the PR 😃

@christophe-david christophe-david merged commit 51a596a into master Jan 18, 2024
18 of 20 checks passed
@christophe-david christophe-david deleted the setup-optimisation branch January 18, 2024 09:26
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