Semi-Automated explicit instantiation of templated functions in separate compilation units
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 287
- Forks
- 109
- Avg merge
- 4d 41m
- Merged PRs (30d)
- 5
Description
What is the requested feature?
We have various functions that get called after going through a series of "pass thru" template, which are essentially a large manual if/elseif/.../else block (edit...not true any longer. It is now a recursive function call with an if check to see if if the cast succeeded...see ConstitutivePassThruHandler below ) for calling compile time instantiations of functions from a runtime interface. This is all well and good, except that it results in huge compilation units that compile all permutations of the pass-thru. This has two problems: 1) long compile times that are not able to use parallelism, 2) large memory requirements for these bloated compilation units.
example:
template< typename LAMBDA >
void constitutiveUpdatePassThru( MultiFluidBase const & fluid,
LAMBDA && lambda )
{
ConstitutivePassThruHandler< DeadOilFluid,
BlackOilFluid,
#ifdef GEOSX_USE_PVTPackage
CompositionalMultiphaseFluid,
#endif
CO2BrinePhillipsFluid,
CO2BrineEzrokhiFluid,
CO2BrinePhillipsThermalFluid /*, // if I uncomment the two models at the same time, the compiler segfaults on
Lassen!
CO2BrineEzrokhiThermalFluid*/>::execute( fluid, std::forward< LAMBDA >( lambda ) );
}
and
template< typename TYPE, typename ... TYPES >
struct ConstitutivePassThruHandler< TYPE, TYPES... >
{
template< typename BASE, typename LAMBDA >
static void execute( BASE & relation, LAMBDA && lambda )
{
using Derived = add_const_if_t< TYPE, std::is_const< BASE >::value >;
if( dynamicCast< Derived * >( &relation ) )
{
lambda( static_cast< Derived & >( relation ) );
}
else
{
ConstitutivePassThruHandler< TYPES... >::execute( relation, std::forward< LAMBDA >( lambda ) );
}
}
};
Ideally, the lambda function will call another function that is templated on the strong type of fluid that is passed to execute, which is passed to lambda eventually. For instance, `PVTDriver.cpp has :
constitutiveUpdatePassThru( baseFluid, [&] ( auto & selectedFluid )
{
using FLUID_TYPE = TYPEOFREF( selectedFluid );
runTest< FLUID_TYPE >( selectedFluid, m_table );
} );
We need to have cmake create a bunch of compilation units that look like:
#include "PVTDriverRunTest.hpp"
#include "CompositionalMultiphaseFluid.hpp"
namespace geosx
{
template void PVTDriver::runTest< constitutive::CompositionalMultiphaseFluid >( constitutive::CompositionalMultiphaseFluid &, arrayView2d< real64 > const & );
}
Is your request related to a specific problem?
Long compilation times,
Large memory footprints
failing compilation on CUDA machines
Describe the solution you'd like
We can make a semi-automated process to generate compilation units for each instantiation. The proposed process is as follows:
- We take the templated function/s and place them in either a single header, or a collection of stand-alone headers. In the example above, this is the contents of
PVTDriverRunTest.hpp. - We creates a cmake list of classnames/filenames that contain the various template parameters in the pass-thru function
- We create a "template file" that is the pattern for the compilation units.
- We use cmake to use substitution and generate the compilation units....of course we add the generated compilation units to the list of sources for the module we are in.
Describe alternatives you've considered
JITC
When assigned, developer should coordinate with @klevzoff and @rrsettgast
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.