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

Compile speedup #979

Merged
merged 15 commits into from
Feb 21, 2021
Merged

Compile speedup #979

merged 15 commits into from
Feb 21, 2021

Conversation

speth
Copy link
Member

@speth speth commented Feb 18, 2021

The main goal of this PR is to reduce compile times, which have been creeping upward. It does not address the single biggest single build step, compiling the Cython-generated _cantera.cpp file, which is a project unto itself.

Changes proposed in this pull request

  • Stop using fmt in header-only mode, which speeds up the compilation of each compilation unit that includes fmt
  • Combine most of the source files defining functions in the VCS_SOLVE class. The whole class is a bit too long for one source file, but 2 compilation units is better than 12.
  • Use forward declarations to devolve some includes so that fewer header files are linked to each other. In addition offering a small speedup for a full rebuild, this helps limit the number of source files that have to be rebuilt after a change to any header file.
  • Clean up the constructors for ThermoPhase derivatives. Deprecate a couple of cases which take extra arguments that should be provided using the normal methods for setting parameters (function calls or input files), and eliminate the need for a separate default constructor.
  • Stop using and deprecate the confusing thermo_t typedef
  • Drop CI builds using Python 3.5, which is now end of life
  • Disable debug symbols in CI builds
  • Tweak the "coverage" build to run a little faster by adding the NDEBUG preprocessor define

Results

For the builds using GitHub Actions,

  • The standard Ubuntu builds are ~40% faster
  • The macOS builds are ~16% faster
  • The "docs" build is ~56% faster
  • The runs of the examples are ~16% faster
  • The Windows builds are ~13% faster, though this is somewhat variable
  • The coverage build is ~15% faster

Checklist

  • There is a clear use-case for this code change
  • The commit message has a short title & references relevant issues
  • Build passes (scons build & scons test) and unit tests address code coverage
  • The pull request is ready for review

@speth speth force-pushed the compile-speedup branch 2 times, most recently from 419bd2d to 8edb731 Compare February 18, 2021 16:28
@ischoegl
Copy link
Member

👍 for getting rid of thermo_t

@bryanwweber
Copy link
Member

  • Stop using fmt in header-only mode, which speeds up the compilation of each compilation unit that includes fmt

The upshot of the header-only mode is that we don't have to add a runtime dependency on fmt. Is it feasible to let this be a configurable option? I think for compiled packages/installers (which I guess would just include the Conda libcantera package and the Ubuntu package?), it would be an advantage to use the header only mode because the compilation time is less important.

As a counterpoint, there is an overhead associated with maintaining the separate option. I'm not sure which is better/worse!

@speth
Copy link
Member Author

speth commented Feb 18, 2021

  • Stop using fmt in header-only mode, which speeds up the compilation of each compilation unit that includes fmt

The upshot of the header-only mode is that we don't have to add a runtime dependency on fmt. Is it feasible to let this be a configurable option? I think for compiled packages/installers (which I guess would just include the Conda libcantera package and the Ubuntu package?), it would be an advantage to use the header only mode because the compilation time is less important.

As a counterpoint, there is an overhead associated with maintaining the separate option. I'm not sure which is better/worse!

If you compile using the git submodule, the fmt library code still ends up embedded in the Cantera library, so it doesn't add a runtime dependency unless you build using an external copy of the fmt library.

For the Ubuntu package, where we don't (and shouldn't) use our submodules, having a dependency on fmt is pretty simple, and I don't think something we should shy away from. I'd argue the same is true for Conda, where fmt is available in the main conda channel.

@speth speth force-pushed the compile-speedup branch 2 times, most recently from e4f08e8 to e770385 Compare February 18, 2021 20:36
@bryanwweber
Copy link
Member

If you compile using the git submodule, the fmt library code still ends up embedded in the Cantera library

Even for the shared library? I guess the answer is yes, since there's not a libsundials.so file in the build directory. In that case, the change seems fine to me! We'll need to update the conda recipes in parallel with this change. In fact, I wonder if it'd be better to rely on Conda for more of the dependencies...

@codecov
Copy link

codecov bot commented Feb 18, 2021

Codecov Report

Merging #979 (cd0b133) into main (9d6095a) will increase coverage by 0.00%.
The diff coverage is 66.84%.

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #979   +/-   ##
=======================================
  Coverage   71.56%   71.56%           
=======================================
  Files         370      359   -11     
  Lines       45743    45666   -77     
=======================================
- Hits        32735    32683   -52     
+ Misses      13008    12983   -25     
Impacted Files Coverage Δ
include/cantera/base/AnyMap.h 100.00% <ø> (ø)
include/cantera/base/Array.h 84.00% <ø> (-1.42%) ⬇️
include/cantera/base/FactoryBase.h 79.31% <ø> (ø)
include/cantera/base/utilities.h 88.88% <ø> (ø)
include/cantera/base/xml.h 100.00% <ø> (ø)
include/cantera/equil/ChemEquil.h 100.00% <ø> (ø)
include/cantera/equil/MultiPhase.h 100.00% <ø> (+3.44%) ⬆️
include/cantera/kinetics/BulkKinetics.h 100.00% <ø> (ø)
include/cantera/kinetics/Falloff.h 75.00% <ø> (ø)
include/cantera/kinetics/FalloffMgr.h 100.00% <ø> (ø)
... and 185 more

Continue to review full report at Codecov.

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

@speth
Copy link
Member Author

speth commented Feb 18, 2021

If you compile using the git submodule, the fmt library code still ends up embedded in the Cantera library

Even for the shared library? I guess the answer is yes, since there's not a libsundials.so file in the build directory. In that case, the change seems fine to me!

Yes, even for the shared library. We bundle everything that we compile into one library file. For things that we don't compile (specified by system_blah=y), then we link externally.

We'll need to update the conda recipes in parallel with this change. In fact, I wonder if it'd be better to rely on Conda for more of the dependencies...

I'd agree that it's probably a good idea, but I don't see why we have to. Doesn't the conda recipe currently use the submodule for fmt and yaml-cpp? If so, I don't think anything needs to change immediately.

@speth speth marked this pull request as ready for review February 18, 2021 21:49
While using the fmt library in header-only mode was convenient,
Cantera uses this library in so many separate source files that using
it in this mode was noticably increasing overall compilation time.
Copy link
Member

@bryanwweber bryanwweber left a comment

Choose a reason for hiding this comment

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

Some minor formatting suggestions/questions. Looks good otherwise, refactoring is nice. Thank you for doing this!

Comment on lines -155 to -160
//! Calculate the pressure from the ideal gas law
doublereal pressure_ig() const {
return (m_thermo->molarDensity() * GasConstant *
m_thermo->temperature());
}

Copy link
Member

Choose a reason for hiding this comment

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

Just double checking that removing this entirely is the intention, since you created a new function in MultiTransport.h.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, in the MixTransport class, it was a protected member of that was not actually used.

In the case of MultiTransport, the method is used, so I moved the definition to the .cpp file because doing so eliminates the need to have the full definition of ThermoPhase available in MultiTransport.h.

include/cantera/zeroD/ReactorNet.h Outdated Show resolved Hide resolved
@@ -267,7 +269,7 @@ void Kinetics::checkReactionBalance(const Reaction& R)
}
}

void Kinetics::selectPhase(const doublereal* data, const thermo_t* phase,
void Kinetics::selectPhase(const doublereal* data, const ThermoPhase* phase,
Copy link
Member

Choose a reason for hiding this comment

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

A chance here to change this to double* instead of doublereal*.

Copy link
Member Author

Choose a reason for hiding this comment

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

I took the opportunity to update this in a few other places as well.

src/zeroD/FlowReactor.cpp Outdated Show resolved Hide resolved
@bryanwweber
Copy link
Member

One other comment, can you add a "why/how it works briefly" to the commit messages for a045740 and 88ea0f3? I think that'll help if anyone goes to look why those arguments are there.

Code for the VCS_SOLVE class, which was split up among 12 source files,
is now consolidated into just vcs_solve.cpp and vcs_solve_TP.cpp.

This reduces the amount of time spent compiling the VCS solver by ~50%.
For classes derived from ThermoPhase, instead of having separate
constructors for the default constructor and the constructor which
takes an input file and phase id, we can use the case where both
arguments are the default (empty string) to construct a phase without
using an input file. This eliminates the need to repeat any
initialization that takes place in the constructor.
Keeping debug symbols around results in much larger object files,
which in turn get copied into the various libraries and test
executables, and the extra I/O from reading and writing all of these
larger files slows down the build.
Compiling with the NDEBUG macro defined skips assertion checks, such
as those in standard library code. Skipping these checks allows the
tests to run slightly faster.

Compiling with a system copy of Sundials speeds up running the test
suite slightly because the Sundials library being used is still
compiled with optimizations turned on, as opposed to the code within
Cantera, that has to be compiled without optimizations so that the
line coverage will be accurate.
Python 3.5 reached end of life in September 2020.
@bryanwweber bryanwweber merged commit d557e50 into Cantera:main Feb 21, 2021
@speth speth deleted the compile-speedup branch February 21, 2021 22:38
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.

3 participants