QRandomGenerator: optimize for the common use case
The most common uses of QRandomGenerator are getting 32- and 64-bit quantities, either through the generate() and generate64() functions or by ones that call those, like bounded() or generateDouble(). So optimize for those with the same entry point by returning one 64-bit value from the _fillRange() function. Further optimize by not requiring a buffer for those two cases, which required us to replace the (begin, end) parameters with (begin, count). Change-Id: I3eb349b832c14610895efffd16356859eecd5397 Reviewed-by: Lars Knoll <lars.knoll@qt.io>bb10
parent
d0c4d18b01
commit
0096562299
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2019 Intel Corporation.
|
||||
** Copyright (C) 2020 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
|
|
@ -1177,22 +1177,32 @@ bool operator==(const QRandomGenerator &rng1, const QRandomGenerator &rng2)
|
|||
/*!
|
||||
\internal
|
||||
|
||||
Fills the range pointed by \a buffer and \a bufferEnd with 32-bit random
|
||||
values. The buffer must be correctly aligned.
|
||||
Fills the range pointed by \a buffer with \a count 32-bit random values.
|
||||
The buffer must be correctly aligned.
|
||||
|
||||
Returns the value of the first two 32-bit entries as a \c{quint64}.
|
||||
*/
|
||||
void QRandomGenerator::_fillRange(void *buffer, void *bufferEnd)
|
||||
quint64 QRandomGenerator::_fillRange(void *buffer, qptrdiff count)
|
||||
{
|
||||
// Verify that the pointers are properly aligned for 32-bit
|
||||
Q_ASSERT(quintptr(buffer) % sizeof(quint32) == 0);
|
||||
Q_ASSERT(quintptr(bufferEnd) % sizeof(quint32) == 0);
|
||||
quint32 *begin = static_cast<quint32 *>(buffer);
|
||||
quint32 *end = static_cast<quint32 *>(bufferEnd);
|
||||
Q_ASSERT(count >= 0);
|
||||
Q_ASSERT(buffer || count <= 2);
|
||||
|
||||
if (type == SystemRNG || Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) & (UseSystemRNG|SetRandomData)))
|
||||
return SystemGenerator::self().generate(begin, end);
|
||||
quint64 dummy;
|
||||
quint32 *begin = static_cast<quint32 *>(buffer ? buffer : &dummy);
|
||||
quint32 *end = begin + count;
|
||||
|
||||
SystemAndGlobalGenerators::PRNGLocker lock(this);
|
||||
std::generate(begin, end, [this]() { return storage.engine()(); });
|
||||
if (type == SystemRNG || Q_UNLIKELY(uint(qt_randomdevice_control.loadAcquire()) & (UseSystemRNG|SetRandomData))) {
|
||||
SystemGenerator::self().generate(begin, end);
|
||||
} else {
|
||||
SystemAndGlobalGenerators::PRNGLocker lock(this);
|
||||
std::generate(begin, end, [this]() { return storage.engine()(); });
|
||||
}
|
||||
|
||||
if (end - begin == 1)
|
||||
return *begin;
|
||||
return begin[0] | (quint64(begin[1]) << 32);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2017 Intel Corporation.
|
||||
** Copyright (C) 2020 Intel Corporation.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the QtCore module of the Qt Toolkit.
|
||||
|
|
@ -83,16 +83,12 @@ public:
|
|||
|
||||
quint32 generate()
|
||||
{
|
||||
quint32 ret;
|
||||
fillRange(&ret, 1);
|
||||
return ret;
|
||||
return _fillRange(nullptr, 1);
|
||||
}
|
||||
|
||||
quint64 generate64()
|
||||
{
|
||||
quint32 buf[2];
|
||||
fillRange(buf);
|
||||
return buf[0] | (quint64(buf[1]) << 32);
|
||||
return _fillRange(nullptr, sizeof(quint64) / sizeof(quint32));
|
||||
}
|
||||
|
||||
double generateDouble()
|
||||
|
|
@ -142,13 +138,13 @@ public:
|
|||
template <typename UInt, IfValidUInt<UInt> = true>
|
||||
void fillRange(UInt *buffer, qsizetype count)
|
||||
{
|
||||
_fillRange(buffer, buffer + count);
|
||||
_fillRange(buffer, count * sizeof(UInt) / sizeof(quint32));
|
||||
}
|
||||
|
||||
template <typename UInt, size_t N, IfValidUInt<UInt> = true>
|
||||
void fillRange(UInt (&buffer)[N])
|
||||
{
|
||||
_fillRange(buffer, buffer + N);
|
||||
_fillRange(buffer, N * sizeof(UInt) / sizeof(quint32));
|
||||
}
|
||||
|
||||
// API like std::seed_seq
|
||||
|
|
@ -160,7 +156,7 @@ public:
|
|||
|
||||
void generate(quint32 *begin, quint32 *end)
|
||||
{
|
||||
_fillRange(begin, end);
|
||||
_fillRange(begin, end - begin);
|
||||
}
|
||||
|
||||
// API like std:: random engines
|
||||
|
|
@ -181,7 +177,7 @@ protected:
|
|||
QRandomGenerator(System);
|
||||
|
||||
private:
|
||||
Q_CORE_EXPORT void _fillRange(void *buffer, void *bufferEnd);
|
||||
Q_CORE_EXPORT quint64 _fillRange(void *buffer, qptrdiff count);
|
||||
|
||||
friend class QRandomGenerator64;
|
||||
struct SystemGenerator;
|
||||
|
|
|
|||
Loading…
Reference in New Issue