perf(hash): Hash caching
added ability for composition to stash their own hash values
This commit is contained in:
@@ -112,6 +112,7 @@ namespace fourdst::composition {
|
||||
std::optional<std::vector<atomic::Species>> sortedSpecies; ///< Cached vector of sorted species (by mass).
|
||||
std::optional<std::vector<std::string>> sortedSymbols; ///< Cached vector of sorted species (by mass).
|
||||
std::optional<double> Ye; ///< Cached electron abundance.
|
||||
std::optional<std::size_t> hash;
|
||||
|
||||
/**
|
||||
* @brief Clears all cached values.
|
||||
@@ -124,6 +125,7 @@ namespace fourdst::composition {
|
||||
sortedSymbols = std::nullopt;
|
||||
sortedSpecies = std::nullopt;
|
||||
Ye = std::nullopt;
|
||||
hash = std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,7 +135,7 @@ namespace fourdst::composition {
|
||||
[[nodiscard]] bool is_clear() const {
|
||||
return !canonicalComp.has_value() && !massFractions.has_value() &&
|
||||
!numberFractions.has_value() && !molarAbundances.has_value() && !sortedSymbols.has_value() &&
|
||||
!Ye.has_value() && !sortedSpecies.has_value();
|
||||
!Ye.has_value() && !sortedSpecies.has_value() && !hash.has_value();
|
||||
}
|
||||
};
|
||||
private:
|
||||
@@ -832,6 +834,8 @@ namespace fourdst::composition {
|
||||
return m_molarAbundances.cend();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::size_t hash() const override;
|
||||
|
||||
};
|
||||
|
||||
inline bool operator==(const Composition& a, const Composition& b) noexcept {
|
||||
|
||||
@@ -179,6 +179,8 @@ namespace fourdst::composition {
|
||||
[[nodiscard]] virtual std::map<atomic::Species, double>::iterator end() = 0;
|
||||
[[nodiscard]] virtual std::map<atomic::Species, double>::const_iterator begin() const = 0;
|
||||
[[nodiscard]] virtual std::map<atomic::Species, double>::const_iterator end() const = 0;
|
||||
|
||||
[[nodiscard]] virtual std::size_t hash() const = 0;
|
||||
};
|
||||
|
||||
// ReSharper disable once CppClassCanBeFinal
|
||||
|
||||
@@ -36,6 +36,7 @@ namespace fourdst::composition {
|
||||
[[nodiscard]] size_t getSpeciesIndex(const std::string& symbol) const override { return m_base_composition->getSpeciesIndex(symbol); };
|
||||
[[nodiscard]] size_t getSpeciesIndex(const atomic::Species& species) const override { return m_base_composition->getSpeciesIndex(species); };
|
||||
[[nodiscard]] atomic::Species getSpeciesAtIndex(const size_t index) const override { return m_base_composition->getSpeciesAtIndex(index); }
|
||||
[[nodiscard]] size_t hash() const override { return m_base_composition->hash(); };
|
||||
|
||||
[[nodiscard]] std::map<atomic::Species, double>::iterator begin() override { return m_base_composition->begin(); };
|
||||
[[nodiscard]] std::map<atomic::Species, double>::iterator end() override { return m_base_composition->end(); };
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "fourdst/atomic/atomicSpecies.h"
|
||||
#include "fourdst/atomic/species.h"
|
||||
#include "fourdst/composition/composition.h"
|
||||
#include "fourdst/composition/utils/composition_hash.h"
|
||||
#include "fourdst/composition/utils.h"
|
||||
|
||||
#include "fourdst/composition/exceptions/exceptions_composition.h"
|
||||
@@ -551,6 +552,15 @@ namespace fourdst::composition {
|
||||
return std::make_unique<Composition>(*this);
|
||||
}
|
||||
|
||||
std::size_t Composition::hash() const {
|
||||
if (m_cache.hash.has_value()) {
|
||||
return m_cache.hash.value();
|
||||
}
|
||||
std::size_t hash = utils::CompositionHash::hash_exact(*this);
|
||||
m_cache.hash = hash;
|
||||
return hash;
|
||||
}
|
||||
|
||||
bool Composition::contains(
|
||||
const atomic::Species &species
|
||||
) const noexcept {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
||||
#include "fourdst/atomic/atomicSpecies.h"
|
||||
#include "fourdst/atomic/species.h"
|
||||
@@ -439,3 +440,35 @@ TEST_F(compositionTest, canonicalizeNaNIfAllowed) {
|
||||
ASSERT_EQ(fourdst::composition::utils::CompositionHash::hash_exact(a),
|
||||
fourdst::composition::utils::CompositionHash::hash_exact(b));
|
||||
}
|
||||
|
||||
TEST_F(compositionTest, hash) {
|
||||
fourdst::composition::Composition a, b;
|
||||
a.registerSymbol("H-1"); b.registerSymbol("H-1");
|
||||
a.setMolarAbundance("H-1", 0.6); b.setMolarAbundance("H-1", 0.6);
|
||||
EXPECT_NO_THROW((void)a.hash());
|
||||
EXPECT_EQ(a.hash(), b.hash());
|
||||
}
|
||||
|
||||
TEST_F(compositionTest, hashCaching) {
|
||||
using namespace fourdst::atomic;
|
||||
std::unordered_map<Species, double> abundances ={
|
||||
{H_1, 0.702},
|
||||
{He_4, 0.06},
|
||||
{C_12, 0.001},
|
||||
{N_14, 0.0005},
|
||||
{O_16, 0.22},
|
||||
};
|
||||
fourdst::composition::Composition a(abundances);
|
||||
|
||||
const auto first_hash_clock_start = std::chrono::high_resolution_clock::now();
|
||||
(void)a.hash();
|
||||
const auto first_hash_clock_end = std::chrono::high_resolution_clock::now();
|
||||
const auto first_hash_duration = std::chrono::duration_cast<std::chrono::nanoseconds>(first_hash_clock_end - first_hash_clock_start).count();
|
||||
|
||||
const auto second_hash_clock_start = std::chrono::high_resolution_clock::now();
|
||||
(void)a.hash();
|
||||
const auto second_hash_clock_end = std::chrono::high_resolution_clock::now();
|
||||
const auto second_hash_duration = std::chrono::duration_cast<std::chrono::nanoseconds>(second_hash_clock_end - second_hash_clock_start).count();
|
||||
|
||||
EXPECT_LT(second_hash_duration, first_hash_duration);
|
||||
}
|
||||
Reference in New Issue
Block a user