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
[WIP] Experimental improvement in compile time #1460
Conversation
dea3cdc
to
0669ad3
Compare
4fd3fc6
to
5746372
Compare
It seems the tester has the same issue as my laptop (maybe a ubuntu specific setup that confuses cotire). Anyway, for now I have excluded headers in But the madness continues 😄. Cotire also offers a feature called unity builds, which essentially dumps all C++ code into a fixed number of compilation units (e.g. number of processors available), and therefore reduces a lot of redundant work for the compiler. As far as I understand they are not standard conform, and require a bit of code adjustments on our side (see 2nd commit), but the results are impressive. Same setup as described in my post above now compiles the target
On machines with less CPUs this difference will become even larger, because the user time is now only 1/8th of the time before. There is one translation unit that takes longer than the others, therefore less parallel speedup. Probably Anyway this is not really clean, but before spending much time doing polishing and documenting everything, is this something we want to pursue? |
5746372
to
a3923ed
Compare
CMakeLists.txt
Outdated
# and therefore the whole precompilation | ||
cotire(aspect) | ||
ELSE() | ||
MESSAGE(STATUS "Disabling cotire. Do not precompile external header files.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just omit the second part of the sentence. It reads like a command to the reader ("do not do this" -- to which I would reply "do what?")
internal::Plugins::PluginList<Interface<2> >, | ||
internal::Plugins::PluginList<Interface<3> > > registered_plugins; | ||
aspect::internal::Plugins::PluginList<Interface<2> >, | ||
aspect::internal::Plugins::PluginList<Interface<3> > > registered_plugins; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that all of the changes to the src files could also be merged independently -- they all seem like good ideas in principle.
@@ -1526,8 +1526,15 @@ namespace aspect | |||
// explicit instantiation of the functions we implement in this file | |||
namespace aspect | |||
{ | |||
#ifndef aspect_simulator_defined | |||
#define MAYBE_ADVECTION_FIELD(dim) \ | |||
template struct Simulator<dim>::AdvectionField; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why is this necessary? what is the error message you are trying to work around? this seems to me like fixing a legitimate problem the wrong way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this I would need some help with (template problems).
When I do a unity build with an explicit instantiation of the Simulator class and this line in one translation unit, I get the following error:
In file included from /scratch/gassmoel/aspect-debug/cotire/aspect_CXX_unity.cxx:2118:0:
/raid/gassmoel/software/aspect/source/simulator/helper_functions.cc:1537:35: error: duplicate explicit instantiation of ‘struct aspect::Simulator<2>::AdvectionField’ [-fpermissive]
template struct Simulator<dim>::AdvectionField; \
^
/raid/gassmoel/software/aspect/include/aspect/global.h:384:3: note: in expansion of macro ‘INSTANTIATE’
INSTANTIATIONS(2) \
^
/raid/gassmoel/software/aspect/source/simulator/helper_functions.cc:1555:3: note: in expansion of macro ‘ASPECT_INSTANTIATE’
ASPECT_INSTANTIATE(INSTANTIATE)
^
/raid/gassmoel/software/aspect/source/simulator/helper_functions.cc:1537:35: error: duplicate explicit instantiation of ‘struct aspect::Simulator<3>::AdvectionField’ [-fpermissive]
template struct Simulator<dim>::AdvectionField; \
^
/raid/gassmoel/software/aspect/include/aspect/global.h:385:3: note: in expansion of macro ‘INSTANTIATE’
INSTANTIATIONS(3)
^
/raid/gassmoel/software/aspect/source/simulator/helper_functions.cc:1555:3: note: in expansion of macro ‘ASPECT_INSTANTIATE’
ASPECT_INSTANTIATE(INSTANTIATE)
^
make[3]: *** [CMakeFiles/aspect_unity.dir/cotire/aspect_CXX_unity.cxx.o] Error 1
make[2]: *** [CMakeFiles/aspect_unity.dir/all] Error 2
make[1]: *** [CMakeFiles/aspect_unity.dir/rule] Error 2
1f14dba
to
5c83019
Compare
Just to illustrate the problem, a minimal example of the code we are trying to compile in the unity build looks like this:
appended content from helper_functions.cc:
This problem is more complicated than my everyday knowledge of C++. As far as I can see a definition and instantiation of AdvectionField in core.cc would solve the problem, but that is not pretty either. |
A few comments:
|
I tried this, and putting the explicit instantiation of The right solution would be to make sure that cotire puts |
Ok, cotire uses the property 'SOURCES' of the target 'aspect' to determine the order in which files should go into the unity build. |
Can you do something like
? |
Yes, that was what I did, although helper_functions.cc needs to be before simulator.cc, so I tried (and checked that it works as intended by outputting TARGET_SRC):
I did this within the preparations for the cotire call. Would it be necessary to do this before some other command? I did not find any command like |
this happens inside |
Thanks! That did the trick. #1473 now works without the ugly definitions in core.cc and helper_functions.cc. I had to split the cmake instructions in two parts (reordering source files before setting up the target, and calling cotire afterwards). I will close this PR. #1473 should be ready for a review / merge. |
This resulted out of a discussion in #1458.
GCC reports that 80% of our compile time are spend parsing included header files. This of course would not be necessary, because our headers usually do not change between includes from different source files. I found a nice cmake project called 'cotire' (https://github.com/sakra/cotire) that automatically precompiles headers used in cmake projects. Before discussing drawbacks and limitations, here are some results from compiling aspect in an fresh build directory on my laptop with
make -j8
and a fixed medium CPU frequency (to avoid throttling):master: gcc spends 80% in parsing phase
branch: gcc spends <10% in parsing phase
I wish I had found this a few years ago, when I had a slower laptop 😄. Now there are some limitations:
ASPECT_PRECOMPILE_HEADERS
to allow users to switch this on and off in a simple way.Opinions? I was pretty proud of myself when I found this. I have certainly waited for compiling ASPECT way longer than the few hours it took me to put this together 😄.