aboutsummaryrefslogtreecommitdiff
path: root/src/zencore/stats.cpp
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2024-01-10 12:33:31 +0100
committerGitHub <[email protected]>2024-01-10 12:33:31 +0100
commit304ff53705d6a0f5140ba9e82ce66d6d7f9cb554 (patch)
tree306cfc79a45a0aac74124db358a3c2584bbfed89 /src/zencore/stats.cpp
parentMerge branch 'main' of https://github.com/EpicGames/zen (diff)
downloadzen-304ff53705d6a0f5140ba9e82ce66d6d7f9cb554.tar.xz
zen-304ff53705d6a0f5140ba9e82ce66d6d7f9cb554.zip
remove use of <random> in stats (#628)
the previous implementation was quite slow due to use of mt and uniform_distribution.
Diffstat (limited to 'src/zencore/stats.cpp')
-rw-r--r--src/zencore/stats.cpp48
1 files changed, 43 insertions, 5 deletions
diff --git a/src/zencore/stats.cpp b/src/zencore/stats.cpp
index 087319fa4..7c1a9e086 100644
--- a/src/zencore/stats.cpp
+++ b/src/zencore/stats.cpp
@@ -178,10 +178,49 @@ Meter::Mark(uint64_t Count)
//////////////////////////////////////////////////////////////////////////
-// TODO: should consider a cheaper RNG here, this will run for every thread
-// that gets created
+uint64_t
+rol64(uint64_t x, int k)
+{
+ return (x << k) | (x >> (64 - k));
+}
+
+struct xoshiro256ss_state
+{
+ uint64_t s[4];
+};
+
+uint64_t
+xoshiro256ss(struct xoshiro256ss_state* state)
+{
+ uint64_t* s = state->s;
+ uint64_t const result = rol64(s[1] * 5, 7) * 9;
+ uint64_t const t = s[1] << 17;
+
+ s[2] ^= s[0];
+ s[3] ^= s[1];
+ s[1] ^= s[2];
+ s[0] ^= s[3];
-thread_local std::mt19937_64 ThreadLocalRng;
+ s[2] ^= t;
+ s[3] = rol64(s[3], 45);
+
+ return result;
+}
+
+class xoshiro256
+{
+public:
+ uint64_t operator()() { return xoshiro256ss(&m_State); }
+ static constexpr uint64_t min() { return 0; }
+ static constexpr uint64_t max() { return ~(0ull); }
+
+private:
+ xoshiro256ss_state m_State{0xf0fefaf9, 0xbeeb5238, 0x48472397, 0x58858558};
+};
+
+thread_local xoshiro256 ThreadLocalRng;
+
+//////////////////////////////////////////////////////////////////////////
UniformSample::UniformSample(uint32_t ReservoirSize) : m_Values(ReservoirSize)
{
@@ -222,8 +261,7 @@ UniformSample::Update(int64_t Value)
// Randomly choose an old entry to potentially replace (the probability
// of replacing an entry diminishes with time)
- std::uniform_int_distribution<uint64_t> UniformDist(0, Count);
- uint64_t SampleIndex = UniformDist(ThreadLocalRng);
+ const uint64_t SampleIndex = ThreadLocalRng() % Count;
if (SampleIndex < Size)
{