From e48b62f231323c18431569603316a8905d96f916 Mon Sep 17 00:00:00 2001 From: Emily Boudreaux Date: Sat, 6 Dec 2025 16:35:35 -0500 Subject: [PATCH] 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) --- src/include/gridfire/engine/engine_graph.h | 1 + src/include/gridfire/utils/hashing.h | 18 ++++++++++++++++++ src/lib/engine/engine_graph.cpp | 8 +++++++- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/include/gridfire/engine/engine_graph.h b/src/include/gridfire/engine/engine_graph.h index 5698cd47..4a1f2264 100644 --- a/src/include/gridfire/engine/engine_graph.h +++ b/src/include/gridfire/engine/engine_graph.h @@ -882,6 +882,7 @@ namespace gridfire::engine { mutable CppAD::ADFun 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 m_local_abundance_cache; + mutable std::unordered_map> m_stepDerivativesCache; bool m_has_been_primed = false; ///< Flag indicating if the engine has been primed. diff --git a/src/include/gridfire/utils/hashing.h b/src/include/gridfire/utils/hashing.h index 0905ada9..58922cf4 100644 --- a/src/include/gridfire/utils/hashing.h +++ b/src/include/gridfire/utils/hashing.h @@ -3,6 +3,7 @@ #include #include +#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(T9)); + hash = hash_combine(hash, std::bit_cast(rho)); + return hash; + } } diff --git a/src/lib/engine/engine_graph.cpp b/src/lib/engine/engine_graph.cpp index e1999e87..34cf7152 100644 --- a/src/lib/engine/engine_graph.cpp +++ b/src/lib/engine/engine_graph.cpp @@ -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 bare_rates; std::vector 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 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 result = calculateAllDerivatives(