Hi. I make extensive use of the random function, and I noticed that on the Arduino Uno R4 the random() funtion is veeery slooow. Is there a faster replacement for it?
try getting the current millis(). essentially a random number.
You must be kidding β¦
You can have a look at https://forum.arduino.cc/t/the-reliable-but-not-very-sexy-way-to-seed-random/65872/53 from the days of AVR based Arduinos.
I don't have a R4 WiFi so don't know how slow slow is
So this might be faster and might be better.
Hi @arduinomarc. There is a discussion on the subject, and explanation, here:
hardware random number generators typically generate numbers significantly slower than the processor clock rate, although the times mentioned in @ptillisch's link (100ms+) seem quite excessive. ![]()
Renesas doesn't say much about their TRNG, nor do they document that library function that the Arduino code uses (which actually fetches 128bits, and throws away the rest) but the TRNG in the SAMD51 says it takes 84 clocks to generate 32bits.
Renesas considers the TRNG part of their Crypto support, which probably explains the lack of documentation, so it's probably intended for generating one-time keys for use by crypto stuff. ![]()
It doesn't help that the Arduino code "opens" and "closes" the Crypto engine for each random call (and it's not documented how long those take, either!)
You can disable the use of the TRNG by calling randomSeed
This is explicit, So you could do something like:
randomSeed(random(MAX_LONG));
and subsequent calls to random() would use the (fast) PRNG instead...
If you don't need too many random numbers you can generate them at the top of the program, or in setup(), or a batch of them whenever you have time, and store them in an array.
#include <stdint.h>
uint32_t fast_rand() {
static uint32_t seed = 2463534242; // you can change this seed
seed = seed * 1664525 + 1013904223;
return seed;
}
Your linear congruential generator is extremely fast and requires minimal code, so it is suitable for lightweight applications like basic simulations, simple games, or embedded systems where performance is critical and randomness quality is not.
Studies have shown though that the quality is poor by modern standards. It has noticeable correlations especially in the lower bits.
There are better statistical behavior alternatives β have a look at PCG (Permuted Congruential Generator) and Xoshiro (aka XOR/Shift/Rotate) where Seed initialization must be done externally with good entropy - so you pay the 100ms once or four tines only.
uint64_t pcgState = 0x853c49e6748fea9bULL; // your 64-bit seed here
uint32_t pcg32() {
uint64_t oldState = pcgState;
pcgState = oldState * 6364136223846793005ULL + 1;
uint32_t xorshifted = ((oldState >> 18u) ^ oldState) >> 27u;
uint32_t rot = oldState >> 59u;
return (xorshifted >> rot) | (xorshifted << ((-rot) & 31));
}
Or
uint64_t xoshiroState[4] = {1, 2, 3, 4}; // Replace with four non-zero 64-bit seed values
uint64_t rotl(const uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
uint64_t xoshiro256pp() {
uint64_t *s = xoshiroState;
uint64_t result = rotl(s[0] + s[3], 23) + s[0];
uint64_t t = s[1] << 17;
s[2] ^= s[0];
s[3] ^= s[1];
s[1] ^= s[2];
s[0] ^= s[3];
s[2] ^= t;
s[3] = rotl(s[3], 45);
return result;
}
You must replace the seed values before using these functions.
β They can never produce true randomness but can simulate it pretty well for most practical purposes except crypto or fairness-critical tasks as they are designed for speed and good statistical properties but their output is deterministic and can be predicted if the internal state or seed is known.
For cryptography or fairness, you need cryptographically secure random number generators (CSPRNGs) that resist prediction and manipulation and that comes at a cost.
Some true random number generators include built-in delays to enhance security by preventing certain cryptographic attacks. These delays limit how quickly the device produces random values, making it harder for attackers to perform timing analysis or force the generator into predictable states. By slowing down the output rate and controlling access to the entropy source, these delays help protect against side-channel attacks and improve the overall unpredictability and robustness of the random numbers.
β this is essential for cryptographic use and I guess thatβs why they went for fast random if you build a seed with randomSeed() as most games on Arduino would do so I guess ?
Yeah but author didn't say what for he need this generator. May be he is generating nice RGB patterns or something like that, where we don't really need "real randomness".
To increase security of a simple linear PRNG, one can use one dedicated low-priority process (on a hrdware which does support multitasking), which maintain a pool of random data, periodically reseeding small, lightweight PRNG. This task can slowly acquire real random data by reading floating analog input, and once read - disturb PRNG sequence flow with this random data. For example by reseeding it or directly XORing PRNG's state structure
It would be nice if assorted Arduinos used identical or at least similar RNGs for the default random() functions.
"Random enough for games and such" is much different than "random enough for cryptography", and there is little point to going to the trouble of a "really good" RNG for most of the things that are likely to be done on Arduino-class boards.
I'll do some experiments with the R4 RNG to see if I can figure out where the bottleneck is...
Apparently the Arduino trng() function spends most of it's time initializing the R4 SCE, and neither the R4 code nor the Renesas-provided code check whether it has already been initialized ![]()
Initializing the SCE drops the random() time to about 20us.
Well, as I said - you can combine that simple LC-PRNG with analogRead(). Say, reseed the PRNG, by XORing its state variable (32 bit) with what was read from the floating pin. And if this reseeding would be done in a separate task (on a multitasking MCU) then you'll get zero jitter (time delta between consecutive calls to random())
Then, you can generate a huge array and check it with online tools for randomness. At least this is what I would do if I need fast & secure PRNG
Ugh. I wish I did not have to write this yet again. Using analogRead to seed any random number generator is a terrible choice. Please refrain from making that recommendation.
While I have your attention...
...is simply false. There is no such thing as "increase security" with simple generators. I'm hoping you meant "increase quality".
In addition, neither of those is on-topic for this thread. Please try to stay on-topic.
why? is it not random enough? You can choose floating pin that is far away from pins that are doing something. You'll get less crosstalk on your ADC pin.
Not arguing, just asking.
Initial post: "Arduino Uno R4 the random() funtion is veeery slooow. Is there a faster replacement for it?"
So we are on topic. We are trying to find a faster replacement for "random()".
How many clock sources Arduino UNO has? If it is more than one, then one can try to get some entropy from clocks difference. Say, you have 2 independed clock sources: Xtal and RC oscillator. You can compare phase shift between these two. It will give few bits of entropy.
Also, I forgot to mention: if you are reading ADC as entropy source (say, 10 bit) and you have your PRNG state variable of 32 bit, then it would be good idea to duplicate those 10 bits into 30 bits and then XOR with state variable.
It is always a tradeoff between speed and randomness.
If I would need TRNG, then I go with a diode, near it reverse breakdown voltage (may be Zener would work even better). Diode will generate truly random white noise (quantum mechanics agrees with that :)), which is then fed to opamp, or any simple single BJT amplifier and then fed to ADC pin.
This sort of randomness is only needed for secure protocols, like SSL, TLS or IPSec. I don't think TopicStarter implements anything like that.
Seeding has nothing to do with speed. Secure has nothing to do with speed. Get back on topic. Last warning.
In which case, create a new topic and ask.
Actually it could according to