perf(GraphEngine): more caching

Added more agressive caching, regained about another 50% performance gain. Solar model over 10Gyr now takes roughly 400ms (as opposed to 1 second before)
This commit is contained in:
2025-12-06 16:35:35 -05:00
parent e95881d917
commit e48b62f231
3 changed files with 26 additions and 1 deletions

View File

@@ -882,6 +882,7 @@ namespace gridfire::engine {
mutable CppAD::ADFun<double> m_epsADFun; ///< CppAD function for the energy generation rate.
mutable CppAD::sparse_jac_work m_jac_work; ///< Work object for sparse Jacobian calculations.
mutable std::vector<double> m_local_abundance_cache;
mutable std::unordered_map<size_t, StepDerivatives<double>> m_stepDerivativesCache;
bool m_has_been_primed = false; ///< Flag indicating if the engine has been primed.

View File

@@ -3,6 +3,7 @@
#include <cstdint>
#include <functional>
#include "fourdst/composition/utils/composition_hash.h"
#include "gridfire/exceptions/exceptions.h"
#include "gridfire/reaction/reaction.h"
@@ -69,4 +70,21 @@ namespace gridfire::utils {
seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
return seed;
}
inline std::size_t hash_state(
const fourdst::composition::CompositionAbstract& comp,
const double T9,
const double rho,
const reaction::ReactionSet& reactions
) noexcept {
constexpr std::size_t seed = 0;
std::size_t comp_hash = fourdst::composition::utils::CompositionHash::hash_exact(comp);
for (const auto& reaction : reactions) {
comp_hash = hash_combine(comp_hash, hash_reaction(*reaction));
}
std::size_t hash = hash_combine(seed, comp_hash);
hash = hash_combine(hash, std::bit_cast<std::size_t>(T9));
hash = hash_combine(hash, std::bit_cast<std::size_t>(rho));
return hash;
}
}

View File

@@ -147,6 +147,10 @@ namespace gridfire::engine {
LOG_TRACE_L3(m_logger, "Calculating RHS and Energy in GraphEngine at T9 = {}, rho = {}.", T9, rho);
const double Ye = comp.getElectronAbundance();
if (m_usePrecomputation) {
const std::size_t state_hash = utils::hash_state(comp, T9, rho, activeReactions);
if (m_stepDerivativesCache.contains(state_hash)) {
return m_stepDerivativesCache.at(state_hash);
}
LOG_TRACE_L3(m_logger, "Using precomputation for reaction rates in GraphEngine calculateRHSAndEnergy.");
std::vector<double> bare_rates;
std::vector<double> bare_reverse_rates;
@@ -164,7 +168,9 @@ namespace gridfire::engine {
LOG_TRACE_L3(m_logger, "Precomputed {} forward and {} reverse reaction rates for active reactions.", bare_rates.size(), bare_reverse_rates.size());
// --- The public facing interface can always use the precomputed version since taping is done internally ---
return calculateAllDerivativesUsingPrecomputation(comp, bare_rates, bare_reverse_rates, T9, rho, activeReactions);
StepDerivatives<double> result = calculateAllDerivativesUsingPrecomputation(comp, bare_rates, bare_reverse_rates, T9, rho, activeReactions);
m_stepDerivativesCache.insert(std::make_pair(state_hash, result));
return result;
} else {
LOG_TRACE_L2(m_logger, "Not using precomputation for reaction rates in GraphEngine calculateRHSAndEnergy.");
StepDerivatives<double> result = calculateAllDerivatives<double>(