-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
-- e54b9c7bbb0c58475676c268e2e19c69f4bce48a by Jorg Brown <[email protected]>: Tweak ABSL_PREDICT_TRUE slightly, for better code on some platforms and/or optimization levels. "false || (x)" is more verbose than "!!(x)", but ultimately more efficient. For example, given this code: void InitIfNecessary() { if (ABSL_PREDICT_TRUE(NeedsInit())) { SlowInitIfNecessary(); } } Clang with default optimization level will produce: Before this CL After this CL InitIfNecessary: InitIfNecessary: push rbp push rbp mov rbp, rsp mov rbp, rsp call NeedsInit call NeedsInit xor al, -1 xor al, -1 test al, 1 test al, 1 jne .LBB2_1 jne .LBB3_1 jmp .LBB2_2 jmp .LBB3_2 .LBB2_1: .LBB3_1: call SlowInitIfNecessary call SlowInitIfNecessary .LBB2_2: .LBB3_2: pop rbp pop rbp ret ret PiperOrigin-RevId: 276401386 -- 0a3c4dfd8342bf2b1b11a87f1c662c883f73cab7 by Abseil Team <[email protected]>: Fix comment nit: sem_open => sem_init. The code calls sem_init, not sem_open, to initialize an unnamed semaphore. (sem_open creates or opens a named semaphore.) PiperOrigin-RevId: 276344072 -- b36a664e9459057509a90e83d3482e1d3a4c44c7 by Abseil Team <[email protected]>: Fix typo in flat_hash_map.h: exchaged -> exchanged PiperOrigin-RevId: 276295792 -- 7bbd8d18276eb110c8335743e35fceb662ddf3d6 by Samuel Benzaquen <[email protected]>: Add assertions to verify use of iterators. PiperOrigin-RevId: 276283300 -- 677398a8ffcb1f59182cffe57a4fe7ff147a0404 by Laramie Leavitt <[email protected]>: Migrate distribution_impl.h/cc to generate_real.h/cc. Combine the methods RandU64To<Float,Double> into a single method: GenerateRealFromBits(). Remove rejection sampling from absl::uniform_real_distribution. PiperOrigin-RevId: 276158675 -- c60c9d11d24b0c546329d998e78e15a84b3153f5 by Abseil Team <[email protected]>: Internal change PiperOrigin-RevId: 276126962 -- 4c840cab6a8d86efa29b397cafaf7520eece68cc by Andy Soffer <[email protected]>: Update CMakeLists.txt to address #365. This does not cover every platform, but it does at least address the first-order issue of assuming gcc implies x86. PiperOrigin-RevId: 276116253 -- 98da366e6b5d51afe5d7ac6722126aca23d85ee6 by Abseil Team <[email protected]>: Internal change PiperOrigin-RevId: 276097452 GitOrigin-RevId: e54b9c7bbb0c58475676c268e2e19c69f4bce48a Change-Id: I02d84454bb71ab21ad3d39650acf6cc6e36f58d7
- Loading branch information
1 parent
19b021c
commit 078b89b
Showing
28 changed files
with
739 additions
and
370 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
// Copyright 2019 The Abseil Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#include "absl/base/internal/exponential_biased.h" | ||
|
||
#include <stdint.h> | ||
|
||
#include <atomic> | ||
#include <cmath> | ||
#include <limits> | ||
|
||
#include "absl/base/attributes.h" | ||
#include "absl/base/optimization.h" | ||
|
||
namespace absl { | ||
namespace base_internal { | ||
|
||
// The algorithm generates a random number between 0 and 1 and applies the | ||
// inverse cumulative distribution function for an exponential. Specifically: | ||
// Let m be the inverse of the sample period, then the probability | ||
// distribution function is m*exp(-mx) so the CDF is | ||
// p = 1 - exp(-mx), so | ||
// q = 1 - p = exp(-mx) | ||
// log_e(q) = -mx | ||
// -log_e(q)/m = x | ||
// log_2(q) * (-log_e(2) * 1/m) = x | ||
// In the code, q is actually in the range 1 to 2**26, hence the -26 below | ||
int64_t ExponentialBiased::Get(int64_t mean) { | ||
if (ABSL_PREDICT_FALSE(!initialized_)) { | ||
Initialize(); | ||
} | ||
|
||
uint64_t rng = NextRandom(rng_); | ||
rng_ = rng; | ||
|
||
// Take the top 26 bits as the random number | ||
// (This plus the 1<<58 sampling bound give a max possible step of | ||
// 5194297183973780480 bytes.) | ||
// The uint32_t cast is to prevent a (hard-to-reproduce) NAN | ||
// under piii debug for some binaries. | ||
double q = static_cast<uint32_t>(rng >> (kPrngNumBits - 26)) + 1.0; | ||
// Put the computed p-value through the CDF of a geometric. | ||
double interval = (std::log2(q) - 26) * (-std::log(2.0) * mean); | ||
// Very large values of interval overflow int64_t. To avoid that, we will cheat | ||
// and clamp any huge values to (int64_t max)/2. This is a potential source of | ||
// bias, but the mean would need to be such a large value that it's not likely | ||
// to come up. For example, with a mean of 1e18, the probability of hitting | ||
// this condition is about 1/1000. For a mean of 1e17, standard calculators | ||
// claim that this event won't happen. | ||
if (interval > static_cast<double>(std::numeric_limits<int64_t>::max() / 2)) { | ||
return std::numeric_limits<int64_t>::max() / 2; | ||
} | ||
|
||
return static_cast<int64_t>(interval); | ||
} | ||
|
||
void ExponentialBiased::Initialize() { | ||
// We don't get well distributed numbers from `this` so we call NextRandom() a | ||
// bunch to mush the bits around. We use a global_rand to handle the case | ||
// where the same thread (by memory address) gets created and destroyed | ||
// repeatedly. | ||
ABSL_CONST_INIT static std::atomic<uint32_t> global_rand(0); | ||
uint64_t r = reinterpret_cast<uint64_t>(this) + | ||
global_rand.fetch_add(1, std::memory_order_relaxed); | ||
for (int i = 0; i < 20; ++i) { | ||
r = NextRandom(r); | ||
} | ||
rng_ = r; | ||
initialized_ = true; | ||
} | ||
|
||
} // namespace base_internal | ||
} // namespace absl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
// Copyright 2019 The Abseil Authors. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
#ifndef ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_ | ||
#define ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_ | ||
|
||
#include <stdint.h> | ||
|
||
namespace absl { | ||
namespace base_internal { | ||
|
||
// ExponentialBiased provides a small and fast random number generator for a | ||
// rounded exponential distribution. This generator doesn't requires very little | ||
// state doesn't impose synchronization overhead, which makes it useful in some | ||
// specialized scenarios. | ||
// | ||
// For the generated variable X, X ~ floor(Exponential(1/mean)). The floor | ||
// operation introduces a small amount of bias, but the distribution is useful | ||
// to generate a wait time. That is, if an operation is supposed to happen on | ||
// average to 1/mean events, then the generated variable X will describe how | ||
// many events to skip before performing the operation and computing a new X. | ||
// | ||
// The mathematically precise distribution to use for integer wait times is a | ||
// Geometric distribution, but a Geometric distribution takes slightly more time | ||
// to compute and when the mean is large (say, 100+), the Geometric distribution | ||
// is hard to distinguish from the result of ExponentialBiased. | ||
// | ||
// This class is thread-compatible. | ||
class ExponentialBiased { | ||
public: | ||
// The number of bits set by NextRandom. | ||
static constexpr int kPrngNumBits = 48; | ||
|
||
// Generates the floor of an exponentially distributed random variable by | ||
// rounding the value down to the nearest integer. The result will be in the | ||
// range [0, int64_t max / 2]. | ||
int64_t Get(int64_t mean); | ||
|
||
// Computes a random number in the range [0, 1<<(kPrngNumBits+1) - 1] | ||
// | ||
// This is public to enable testing. | ||
static uint64_t NextRandom(uint64_t rnd); | ||
|
||
private: | ||
void Initialize(); | ||
|
||
uint64_t rng_{0}; | ||
bool initialized_{false}; | ||
}; | ||
|
||
// Returns the next prng value. | ||
// pRNG is: aX+b mod c with a = 0x5DEECE66D, b = 0xB, c = 1<<48 | ||
// This is the lrand64 generator. | ||
inline uint64_t ExponentialBiased::NextRandom(uint64_t rnd) { | ||
const uint64_t prng_mult = uint64_t{0x5DEECE66D}; | ||
const uint64_t prng_add = 0xB; | ||
const uint64_t prng_mod_power = 48; | ||
const uint64_t prng_mod_mask = | ||
~((~static_cast<uint64_t>(0)) << prng_mod_power); | ||
return (prng_mult * rnd + prng_add) & prng_mod_mask; | ||
} | ||
|
||
} // namespace base_internal | ||
} // namespace absl | ||
|
||
#endif // ABSL_BASE_INTERNAL_EXPONENTIAL_BIASED_H_ |
Oops, something went wrong.