When you need pseudo-random numbers in C code, commonly used routines are `random()`

, `rand()`

and `rand_r(unsigned int*)`

. First and foremost, it is important to know that none of these routines produce high quality random numbers suitable for cryptographic use. But there are cases where you just need some random looking numbers. Let’s focus on these use-cases in this blog post.

For example, let’s assume you have a multi-threaded OpenMP program where you need to generate different pseudo-random numbers in each thread. A natural approach to this would be the following:

#pragma omp parallel { unsigned seed = omp_get_thread_num(); #pragma omp for for (...) { int rnd = rand_r(&seed); ... } }

Each thread stores its own state of the random number generator and initializes (*seeds*) it with its thread number. Therefore, each thread should obtain different random numbers, although they will be idential on each run due to the deterministically chosen initial values. So, what’s wrong with this code? Let’s have a look at the very first random numbers generated for each thread on macOS 12: