forked from Alepha/Alepha
Add fast random facility.
This is a low-memory-overhead and low-cpu-overhead (per generated bit) random number generator. The repeat cycle is around 2**88. Which means around 2**120 bits are available before a cycle. Which means that about 2**102 12-bit samples are available before repeats. This should be more than sufficient for blob rollover purposes. If 100 million blobs are split per second (absurdly high), then that's about 2**27 per second. If run for 30 years, that's 2**30 seconds. If run across 128 CPUs, that's 2**7 CPUs. Thus 2**(27+30+7) total samples are required before loop. This is 2**64 which is WAAAY less than 2**88. (And this is overly conservative, as these generators should be one-per-thread... so we're really much closer to 2**57, not that it matters.) For this reason, there's no reseed code. The cycle length of mt11213b is significantly longer, however, it has a significantly larger state. One goal here is to keep the amount of state for this generator to a single cache line. As such, if the cycle length is later shown to be significantly smaller than 2**48 or so, a reseed code path may need to be added. (This is on the assumption that the above described intensive run would run for more than 1 million seconds, or about two weeks.)
This commit is contained in:
@ -12,6 +12,7 @@ add_library( alepha SHARED
|
|||||||
Console.cc
|
Console.cc
|
||||||
ProgramOptions.cc
|
ProgramOptions.cc
|
||||||
string_algorithms.cc
|
string_algorithms.cc
|
||||||
|
fastRandom.cc
|
||||||
word_wrap.cc
|
word_wrap.cc
|
||||||
Thread.cc
|
Thread.cc
|
||||||
delimited_list.cc
|
delimited_list.cc
|
||||||
|
63
fastRandom.cc
Normal file
63
fastRandom.cc
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
static_assert( __cplusplus > 2023'00 );
|
||||||
|
|
||||||
|
#include "fastRandom.h"
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
#include <boost/random/taus88.hpp>
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen ::detail:: fastRandom_m
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
struct FastRandomState
|
||||||
|
{
|
||||||
|
boost::random::taus88 fastRandomState{ std::random_device{}() };
|
||||||
|
std::uint32_t pool;
|
||||||
|
int remainingBits= 0;
|
||||||
|
|
||||||
|
void
|
||||||
|
next()
|
||||||
|
{
|
||||||
|
pool= fastRandomState();
|
||||||
|
remainingBits= 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
refresh()
|
||||||
|
{
|
||||||
|
if( remainingBits == 0 ) next();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t
|
||||||
|
getBit()
|
||||||
|
{
|
||||||
|
refresh();
|
||||||
|
const std::uint32_t rv= pool & 1;
|
||||||
|
--remainingBits;
|
||||||
|
pool>>= 1;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t
|
||||||
|
get( int count )
|
||||||
|
{
|
||||||
|
std::uint32_t rv= 0;
|
||||||
|
while( count-- )
|
||||||
|
{
|
||||||
|
rv<<= 1;
|
||||||
|
rv|= getBit();
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
thread_local FastRandomState fastRandom;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint32_t
|
||||||
|
exports::fastRandomBits( const int numBits )
|
||||||
|
{
|
||||||
|
return fastRandom.get( numBits );
|
||||||
|
}
|
||||||
|
}
|
20
fastRandom.h
Normal file
20
fastRandom.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
static_assert( __cplusplus > 2023'00 );
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Alepha/Alepha.h>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen ::detail:: fastRandom_m
|
||||||
|
{
|
||||||
|
inline namespace exports
|
||||||
|
{
|
||||||
|
std::uint32_t fastRandomBits( int numBits );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Alepha::Hydrogen::inline exports::inline fastRandom_m
|
||||||
|
{
|
||||||
|
using namespace detail::fastRandom_m::exports;
|
||||||
|
}
|
Reference in New Issue
Block a user