Hardware-based Random Number Generator (RDRAND)¶
-
class randomgen.rdrand.RDRAND(seed=
None
, *, retries=10
)¶ Container for the hardware RDRAND random number generator.
- Parameters:¶
- seed=
None
¶ Must be None. Raises if any other value is passed.
- retries=
10
¶ The number of times to retry. On CPUs with many cores it is possible for RDRAND to fail if heavily utilized. retries sets the number of retries before a RuntimeError is raised. Each retry issues a pause instruction which waits a CPU-specific number of cycles (140 on Skylake [1]). The default value of 10 is recommended by Intel ([2]). You can set any value up-to the maximum integer size on your platform if you have issues with errors, although the practical maximum is less than 100. See Notes for more on the error state.
- seed=
- lock¶
Lock instance that is shared so that the same bit git generator can be used in multiple Generators without corrupting the state. Code that generates values from a bit generator should hold the bit generator’s lock.
- Type:¶
Notes
RDRAND is a hardware random number generator that is available on Intel processors from the Ivy Bridge line (2012) or later, and AMD processors starting in 2015.
RDRAND has been audited and is reported to be a secure generator. It is much slower than software BitGenerators and so is only useful in applications where security is more important than performance.
State and Seeding
Results from
RDRAND
are NOT reproducible.RDRAND
uses a hardware generated seed and so cannot be seeded. The state contains a single integer valuestatus
that takes the value 1 if all calls have succeeded and 0 if any fail. A failure of a call to RDRAND does not propagate, and so users much check this value to determine if results are random.Parallel Features
RDRAND
is stateless and so multiple instances can be used in parallel.>>> from numpy.random import Generator >>> from randomgen import RDRAND >>> rg = [Generator(RDRAND()) for _ in range(10)]
Exceptions
Bit generators are designed to run as quickly as possible to produce deterministic but chaotic sequences. With the exception of RDRAND, all other bit generators cannot fail (short of a massive CPU issue). RDRAND can fail to produce a random value if many threads are all utilizing the same random generator, and so it is necessary to check a flag to ensure that the instruction has succeeded. When it does not exceed, an exception should be raised. However, bit generators operate without the Python GIL which means that they cannot directly raise. Instead, if an error is detected when producing random values using RDRAND, the Python error flag is set with a RuntimError. This error must then be checked for. In most applications this happens automatically since the Lock attached to this instance will check the error state when exiting and raise RuntimError.
If you write custom code that uses lower-level function, e.g., the PyCapsule, you will either need to check the status flag in the state structure, or use PyErr_Occurred to see if an error occurred during generation.
To see the exception you will generate, you can run this invalid code
>>> from numpy.random import Generator >>> from randomgen import RDRAND >>> bitgen = RDRAND() >>> state = bitgen.state >>> state["retries"] = -1 # Ensure always fails >>> bitgen.state = state >>> gen = Generator(bitgen)
The next command will always raise RuntimeError.
>>> gen.standard_normal(size=10)
The RDRAND-provided function
random_raw
also checks for success and will raise if not able to use RDRAND>>> bitgen.random_raw()
Note that
random_raw
has been customized for the needs to RDRAND and does not rely on the Lock to raise. Instead it checks the status directly and raises if the status is invalid.Finally, you can directly check if there have been any errors by inspecting the
success
property>>> bitgen = RDRAND() >>> assert bitgen.success # True >>> bitgen.random_raw(10) >>> assert bitgen.success # Still true
You will only ever see an AssertionError if the RDRAND has failed. Since you will first see a RuntimeError, the second assert will not execute without some manual intervention.
No Compatibility Guarantee
RDRAND
is hardware dependent and not reproducible, and so there is no stream guarantee.- Raises:¶
RuntimeError – If RDRAND is not available on the platform.
Examples
>>> from numpy.random import Generator >>> from randomgen import RDRAND >>> rg = Generator(RDRAND()) >>> rg.standard_normal() 0.123 # random
References
Seeding and State¶
|
Compatibility function. |
Get or set the PRNG state |
|
Gets the flag indicating that all calls to RDRAND succeeded |
Parallel generation¶
|
Returns a new bit generator |
Extending¶
CFFI interface |
|
ctypes interface |
Testing¶
|
Return randoms as generated by the underlying BitGenerator |
Custom Lock¶
- class randomgen.rdrand.RaisingLock¶
A Lock that wraps threading.Lock can can raise errors.
Raises the last exception set while the lock was held, if any. It clears the error when the lock is acquired.
Notes
This class has been specially designed for issues unique to RDRAND.