crlib: replace random number generator with wyhash.
Benchmarks shows about 4x increased PRNG perfomance increase comparing to old one. Should slightly reduce per-bot CPU usage.
This commit is contained in:
parent
1263a1a439
commit
726ea72965
13 changed files with 189 additions and 179 deletions
|
|
@ -272,8 +272,10 @@ public:
|
|||
}
|
||||
|
||||
void shuffle () {
|
||||
for (size_t i = length_; i >= 1; --i) {
|
||||
cr::swap (contents_[i - 1], contents_[rg.int_ (i, length_ - 2)]);
|
||||
int32 shuffleLength = length <int32> ();
|
||||
|
||||
for (int32 i = shuffleLength; i >= 1; --i) {
|
||||
cr::swap (contents_[i - 1], contents_[rg.get (i, shuffleLength - 2)]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -352,11 +354,11 @@ public:
|
|||
}
|
||||
|
||||
const T &random () const {
|
||||
return contents_[rg.int_ <size_t> (0, length_ - 1)];
|
||||
return contents_[rg.get (0, length <int32> () - 1)];
|
||||
}
|
||||
|
||||
T &random () {
|
||||
return contents_[rg.int_ <size_t> (0u, length_ - 1u)];
|
||||
return contents_[rg.get (0, length <int32> () - 1)];
|
||||
}
|
||||
|
||||
T *data () {
|
||||
|
|
|
|||
|
|
@ -443,7 +443,7 @@ public:
|
|||
if (boundarySlash != String::InvalidIndex) {
|
||||
boundaryName = localPath.substr (boundarySlash + 1);
|
||||
}
|
||||
StringRef boundaryLine = strings.format ("---crlib_upload_boundary_%d%d%d%d", rg.int_ (0, 9), rg.int_ (0, 9), rg.int_ (0, 9), rg.int_ (0, 9));
|
||||
StringRef boundaryLine = strings.format ("---crlib_upload_boundary_%d%d%d%d", rg.get (0, 9), rg.get (0, 9), rg.get (0, 9), rg.get (0, 9));
|
||||
|
||||
String request, start, end;
|
||||
start.appendf ("--%s\r\n", boundaryLine);
|
||||
|
|
|
|||
|
|
@ -20,49 +20,57 @@
|
|||
|
||||
CR_NAMESPACE_BEGIN
|
||||
|
||||
// random number generator see: https://github.com/preshing/RandomSequence/
|
||||
class Random final : public Singleton <Random> {
|
||||
// based on: https://github.com/jeudesprits/PSWyhash/blob/master/Sources/CWyhash/include/wyhash.h
|
||||
class Random : public Singleton <Random> {
|
||||
private:
|
||||
uint32 index_, offset_;
|
||||
uint64 divider_;
|
||||
uint64 div_ { static_cast <uint64> (1) << 32ull };
|
||||
uint64 state_ { static_cast <uint64> (time (nullptr)) };
|
||||
|
||||
public:
|
||||
explicit Random () {
|
||||
const auto base = static_cast <uint32> (time (nullptr));
|
||||
const auto offset = base + 1;
|
||||
|
||||
index_ = premute (premute (base) + 0x682f0161);
|
||||
offset_ = premute (premute (offset) + 0x46790905);
|
||||
divider_ = (static_cast <uint64> (1)) << 32;
|
||||
}
|
||||
Random () = default;
|
||||
~Random () = default;
|
||||
|
||||
private:
|
||||
uint32 premute (uint32 index) {
|
||||
static constexpr auto prime = 4294967291u;
|
||||
uint64 wyrand64 () {
|
||||
constexpr uint64 wyp0 = 0xa0761d6478bd642full, wyp1 = 0xe7037ed1a0b428dbull;
|
||||
state_ += wyp0;
|
||||
|
||||
if (index >= prime) {
|
||||
return index;
|
||||
}
|
||||
const uint32 residue = (static_cast <uint64> (index) * index) % prime;
|
||||
return (index <= prime / 2) ? residue : prime - residue;
|
||||
return mul (state_ ^ wyp1, state_);
|
||||
}
|
||||
|
||||
uint32 generate () {
|
||||
return premute ((premute (index_++) + offset_) ^ 0x5bf03635);
|
||||
uint32 wyrand32 () {
|
||||
return static_cast <uint32> (wyrand64 ());
|
||||
}
|
||||
|
||||
private:
|
||||
uint64_t rotr (uint64 v, uint32 k) {
|
||||
return (v >> k) | (v << (64 - k));
|
||||
}
|
||||
|
||||
uint64 mul (uint64 a, uint64 b) {
|
||||
uint64 hh = (a >> 32) * (b >> 32);
|
||||
uint64 hl = (b >> 32) * static_cast <uint32> (b);
|
||||
|
||||
uint64 lh = static_cast <uint32> (a) * (b >> 32);
|
||||
uint64 ll = static_cast <uint64> (static_cast <double> (a) * static_cast <double> (b));
|
||||
|
||||
return rotr (hl, 32) ^ rotr (lh, 32) ^ hh ^ ll;
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename U> U int_ (U low, U high) {
|
||||
return static_cast <U> (generate () * (static_cast <double> (high) - static_cast <double> (low) + 1.0) / divider_ + static_cast <double> (low));
|
||||
template <typename U, typename Void = void> U get (U, U) = delete;
|
||||
|
||||
template <typename Void = void> int32 get (int32 low, int32 high) {
|
||||
return static_cast <int32> (wyrand32 () * (static_cast <double> (high) - static_cast <double> (low) + 1.0) / div_ + static_cast <double> (low));
|
||||
}
|
||||
|
||||
float float_ (float low, float high) {
|
||||
return static_cast <float> (generate () * (static_cast <double> (high) - static_cast <double> (low)) / (divider_ - 1) + static_cast <double> (low));
|
||||
template <typename Void = void> float get (float low, float high) {
|
||||
return static_cast <float> (wyrand32 () * (static_cast <double> (high) - static_cast <double> (low)) / (div_ - 1) + static_cast <double> (low));
|
||||
}
|
||||
|
||||
template <typename U> bool chance (const U max, const U maxChance = 100) {
|
||||
return int_ <U> (0, maxChance) < max;
|
||||
public:
|
||||
bool chance (int32 limit) {
|
||||
return get <int32> (0, 100) < limit;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ public:
|
|||
SimdWrap (__m128 m) : m (m)
|
||||
{ }
|
||||
|
||||
|
||||
|
||||
public:
|
||||
SimdWrap normalize () {
|
||||
return { _mm_div_ps (m, _mm_sqrt_ps (wrap_dp_sse2 (m, m))) };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue