mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-08-12 19:59:05 +08:00
Improved the randomness of the tensor random generator
This commit is contained in:
parent
dc524ac716
commit
6795512e59
@ -55,11 +55,11 @@ EIGEN_DEVICE_FUNC uint64_t get_random_seed() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE unsigned PCG_XSH_RS_generator(uint64_t* state) {
|
static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE unsigned PCG_XSH_RS_generator(uint64_t* state, uint64_t stream) {
|
||||||
// TODO: Unify with the implementation in the non blocking thread pool.
|
// TODO: Unify with the implementation in the non blocking thread pool.
|
||||||
uint64_t current = *state;
|
uint64_t current = *state;
|
||||||
// Update the internal state
|
// Update the internal state
|
||||||
*state = current * 6364136223846793005ULL + 0xda3e39cb94b95bdbULL;
|
*state = current * 6364136223846793005ULL + (stream << 1 | 1);
|
||||||
// Generate the random output (using the PCG-XSH-RS scheme)
|
// Generate the random output (using the PCG-XSH-RS scheme)
|
||||||
return static_cast<unsigned>((current ^ (current >> 22)) >> (22 + (current >> 61)));
|
return static_cast<unsigned>((current ^ (current >> 22)) >> (22 + (current >> 61)));
|
||||||
}
|
}
|
||||||
@ -73,17 +73,17 @@ static EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE uint64_t PCG_XSH_RS_state(uint64_t
|
|||||||
|
|
||||||
|
|
||||||
template <typename T> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template <typename T> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
T RandomToTypeUniform(uint64_t* state) {
|
T RandomToTypeUniform(uint64_t* state, uint64_t stream) {
|
||||||
unsigned rnd = PCG_XSH_RS_generator(state);
|
unsigned rnd = PCG_XSH_RS_generator(state, stream);
|
||||||
return static_cast<T>(rnd);
|
return static_cast<T>(rnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
Eigen::half RandomToTypeUniform<Eigen::half>(uint64_t* state) {
|
Eigen::half RandomToTypeUniform<Eigen::half>(uint64_t* state, uint64_t stream) {
|
||||||
Eigen::half result;
|
Eigen::half result;
|
||||||
// Generate 10 random bits for the mantissa
|
// Generate 10 random bits for the mantissa
|
||||||
unsigned rnd = PCG_XSH_RS_generator(state);
|
unsigned rnd = PCG_XSH_RS_generator(state, stream);
|
||||||
result.x = static_cast<uint16_t>(rnd & 0x3ffu);
|
result.x = static_cast<uint16_t>(rnd & 0x3ffu);
|
||||||
// Set the exponent
|
// Set the exponent
|
||||||
result.x |= (static_cast<uint16_t>(15) << 10);
|
result.x |= (static_cast<uint16_t>(15) << 10);
|
||||||
@ -93,14 +93,14 @@ Eigen::half RandomToTypeUniform<Eigen::half>(uint64_t* state) {
|
|||||||
|
|
||||||
|
|
||||||
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
float RandomToTypeUniform<float>(uint64_t* state) {
|
float RandomToTypeUniform<float>(uint64_t* state, uint64_t stream) {
|
||||||
typedef union {
|
typedef union {
|
||||||
uint32_t raw;
|
uint32_t raw;
|
||||||
float fp;
|
float fp;
|
||||||
} internal;
|
} internal;
|
||||||
internal result;
|
internal result;
|
||||||
// Generate 23 random bits for the mantissa mantissa
|
// Generate 23 random bits for the mantissa mantissa
|
||||||
const unsigned rnd = PCG_XSH_RS_generator(state);
|
const unsigned rnd = PCG_XSH_RS_generator(state, stream);
|
||||||
result.raw = rnd & 0x7fffffu;
|
result.raw = rnd & 0x7fffffu;
|
||||||
// Set the exponent
|
// Set the exponent
|
||||||
result.raw |= (static_cast<uint32_t>(127) << 23);
|
result.raw |= (static_cast<uint32_t>(127) << 23);
|
||||||
@ -109,7 +109,7 @@ float RandomToTypeUniform<float>(uint64_t* state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
double RandomToTypeUniform<double>(uint64_t* state) {
|
double RandomToTypeUniform<double>(uint64_t* state, uint64_t stream) {
|
||||||
typedef union {
|
typedef union {
|
||||||
uint64_t raw;
|
uint64_t raw;
|
||||||
double dp;
|
double dp;
|
||||||
@ -118,9 +118,9 @@ double RandomToTypeUniform<double>(uint64_t* state) {
|
|||||||
result.raw = 0;
|
result.raw = 0;
|
||||||
// Generate 52 random bits for the mantissa
|
// Generate 52 random bits for the mantissa
|
||||||
// First generate the upper 20 bits
|
// First generate the upper 20 bits
|
||||||
unsigned rnd1 = PCG_XSH_RS_generator(state) & 0xfffffu;
|
unsigned rnd1 = PCG_XSH_RS_generator(state, stream) & 0xfffffu;
|
||||||
// The generate the lower 32 bits
|
// The generate the lower 32 bits
|
||||||
unsigned rnd2 = PCG_XSH_RS_generator(state);
|
unsigned rnd2 = PCG_XSH_RS_generator(state, stream);
|
||||||
result.raw = (static_cast<uint64_t>(rnd1) << 32) | rnd2;
|
result.raw = (static_cast<uint64_t>(rnd1) << 32) | rnd2;
|
||||||
// Set the exponent
|
// Set the exponent
|
||||||
result.raw |= (static_cast<uint64_t>(1023) << 52);
|
result.raw |= (static_cast<uint64_t>(1023) << 52);
|
||||||
@ -129,14 +129,14 @@ double RandomToTypeUniform<double>(uint64_t* state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
std::complex<float> RandomToTypeUniform<std::complex<float> >(uint64_t* state) {
|
std::complex<float> RandomToTypeUniform<std::complex<float> >(uint64_t* state, uint64_t stream) {
|
||||||
return std::complex<float>(RandomToTypeUniform<float>(state),
|
return std::complex<float>(RandomToTypeUniform<float>(state, stream),
|
||||||
RandomToTypeUniform<float>(state));
|
RandomToTypeUniform<float>(state, stream));
|
||||||
}
|
}
|
||||||
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
std::complex<double> RandomToTypeUniform<std::complex<double> >(uint64_t* state) {
|
std::complex<double> RandomToTypeUniform<std::complex<double> >(uint64_t* state, uint64_t stream) {
|
||||||
return std::complex<double>(RandomToTypeUniform<double>(state),
|
return std::complex<double>(RandomToTypeUniform<double>(state, stream),
|
||||||
RandomToTypeUniform<double>(state));
|
RandomToTypeUniform<double>(state, stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> class UniformRandomGenerator {
|
template <typename T> class UniformRandomGenerator {
|
||||||
@ -155,9 +155,7 @@ template <typename T> class UniformRandomGenerator {
|
|||||||
|
|
||||||
template<typename Index> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template<typename Index> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
T operator()(Index i) const {
|
T operator()(Index i) const {
|
||||||
uint64_t local_state = m_state + i;
|
T result = RandomToTypeUniform<T>(&m_state, i);
|
||||||
T result = RandomToTypeUniform<T>(&local_state);
|
|
||||||
m_state = local_state;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,11 +163,9 @@ template <typename T> class UniformRandomGenerator {
|
|||||||
Packet packetOp(Index i) const {
|
Packet packetOp(Index i) const {
|
||||||
const int packetSize = internal::unpacket_traits<Packet>::size;
|
const int packetSize = internal::unpacket_traits<Packet>::size;
|
||||||
EIGEN_ALIGN_MAX T values[packetSize];
|
EIGEN_ALIGN_MAX T values[packetSize];
|
||||||
uint64_t local_state = m_state + i;
|
|
||||||
for (int j = 0; j < packetSize; ++j) {
|
for (int j = 0; j < packetSize; ++j) {
|
||||||
values[j] = RandomToTypeUniform<T>(&local_state);
|
values[j] = RandomToTypeUniform<T>(&m_state, i);
|
||||||
}
|
}
|
||||||
m_state = local_state;
|
|
||||||
return internal::pload<Packet>(values);
|
return internal::pload<Packet>(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,14 +186,14 @@ struct functor_traits<UniformRandomGenerator<Scalar> > {
|
|||||||
|
|
||||||
|
|
||||||
template <typename T> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template <typename T> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
T RandomToTypeNormal(uint64_t* state) {
|
T RandomToTypeNormal(uint64_t* state, uint64_t stream) {
|
||||||
// Use the ratio of uniform method to generate numbers following a normal
|
// Use the ratio of uniform method to generate numbers following a normal
|
||||||
// distribution. See for example Numerical Recipes chapter 7.3.9 for the
|
// distribution. See for example Numerical Recipes chapter 7.3.9 for the
|
||||||
// details.
|
// details.
|
||||||
T u, v, q;
|
T u, v, q;
|
||||||
do {
|
do {
|
||||||
u = RandomToTypeUniform<T>(state);
|
u = RandomToTypeUniform<T>(state, stream);
|
||||||
v = T(1.7156) * (RandomToTypeUniform<T>(state) - T(0.5));
|
v = T(1.7156) * (RandomToTypeUniform<T>(state, stream) - T(0.5));
|
||||||
const T x = u - T(0.449871);
|
const T x = u - T(0.449871);
|
||||||
const T y = numext::abs(v) + T(0.386595);
|
const T y = numext::abs(v) + T(0.386595);
|
||||||
q = x*x + y * (T(0.196)*y - T(0.25472)*x);
|
q = x*x + y * (T(0.196)*y - T(0.25472)*x);
|
||||||
@ -208,14 +204,14 @@ T RandomToTypeNormal(uint64_t* state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
std::complex<float> RandomToTypeNormal<std::complex<float> >(uint64_t* state) {
|
std::complex<float> RandomToTypeNormal<std::complex<float> >(uint64_t* state, uint64_t stream) {
|
||||||
return std::complex<float>(RandomToTypeNormal<float>(state),
|
return std::complex<float>(RandomToTypeNormal<float>(state, stream),
|
||||||
RandomToTypeNormal<float>(state));
|
RandomToTypeNormal<float>(state, stream));
|
||||||
}
|
}
|
||||||
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template <> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
std::complex<double> RandomToTypeNormal<std::complex<double> >(uint64_t* state) {
|
std::complex<double> RandomToTypeNormal<std::complex<double> >(uint64_t* state, uint64_t stream) {
|
||||||
return std::complex<double>(RandomToTypeNormal<double>(state),
|
return std::complex<double>(RandomToTypeNormal<double>(state, stream),
|
||||||
RandomToTypeNormal<double>(state));
|
RandomToTypeNormal<double>(state, stream));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -234,9 +230,7 @@ template <typename T> class NormalRandomGenerator {
|
|||||||
|
|
||||||
template<typename Index> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
template<typename Index> EIGEN_DEVICE_FUNC EIGEN_STRONG_INLINE
|
||||||
T operator()(Index i) const {
|
T operator()(Index i) const {
|
||||||
uint64_t local_state = m_state + i;
|
T result = RandomToTypeNormal<T>(&m_state, i);
|
||||||
T result = RandomToTypeNormal<T>(&local_state);
|
|
||||||
m_state = local_state;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,11 +238,9 @@ template <typename T> class NormalRandomGenerator {
|
|||||||
Packet packetOp(Index i) const {
|
Packet packetOp(Index i) const {
|
||||||
const int packetSize = internal::unpacket_traits<Packet>::size;
|
const int packetSize = internal::unpacket_traits<Packet>::size;
|
||||||
EIGEN_ALIGN_MAX T values[packetSize];
|
EIGEN_ALIGN_MAX T values[packetSize];
|
||||||
uint64_t local_state = m_state + i;
|
|
||||||
for (int j = 0; j < packetSize; ++j) {
|
for (int j = 0; j < packetSize; ++j) {
|
||||||
values[j] = RandomToTypeNormal<T>(&local_state);
|
values[j] = RandomToTypeNormal<T>(&m_state, i);
|
||||||
}
|
}
|
||||||
m_state = local_state;
|
|
||||||
return internal::pload<Packet>(values);
|
return internal::pload<Packet>(values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user