使用 pthread 在 C 中生成随机数的最正确方法是什么
我有多个线程同时运行,每个线程都必须生成随机数。我想了解是否有可遵循的模式,了解在主线程中使用 srand 初始化随机生成器是否正确,或者每个线程是否必须初始化自己的随机生成器。看来 rand/srand 尚未设计为与线程一起使用,我想知道如何一起处理线程和随机数。 谢谢
编辑:我需要纯随机数,但我也对生成用于测试目的的确定性序列感兴趣。我使用的是linux,但我更喜欢编写尽可能可移植的代码。
I have several threads running concurrently and each of them must generate random numbers. I want to understand if there is a pattern to follow, to understand if it is correct to initialize the random generator with srand in the main thread or if every thread must initialize its own random generator. It seems that rand/srand have not been designed to be used with threads and I'm wondering how I can deal with threads and random numbers together.
Thanks
EDIT: I need pure random numbers, but I'm also interested in generating a deterministic sequence for testing purposes. I'm on linux, but I prefer to write code as portable as possible.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在 Linux 上,您可以使用 rand_r() 作为普通生成器,或者使用 drand48_r() 函数是一个更好的函数。两者都是
rand()
和drand48()
的线程安全替代品,通过采用由当前状态组成的单个参数,而不是使用全局状态。关于您关于初始化的问题,上面的两个生成器都允许您在您想要的任何点播种,因此您不会被迫在生成线程之前播种它们。
On Linux you can use the rand_r() for a mediocre generator or the drand48_r() function for a much better one. Both are thread safe replacements for
rand()
anddrand48()
, by taking a single argument consisting of the current state, instead of using global state.With regard to your question on initialization, both of the generators above allow you to seed at whatever point you desire, so you are not forced to seed them before spawning your threads.
当使用线程并进行模拟等操作时,独立的随机生成器非常重要。首先,它们之间的依赖关系确实会使您的结果产生偏差,然后对随机生成器状态的访问控制机制很可能会减慢执行速度。
在 POSIX 系统上(您似乎在其中),有
*rand48
系列函数,其中erand48
、nrand48
和jrand48
code> 将随机生成器的状态作为输入值。因此,您可以轻松地在每个线程中拥有独立的状态。您可以使用已知的数字(例如线程的数量)来初始化它们,并且您将获得可重现的随机数序列。或者您使用不可预测的内容(例如当前时间和时间)对其进行初始化。每次执行的序列数都不同。When working with threads and doing e.g simulations or so it is very important that you have the random generators independent. First, dependencies between them can really bias your results and then mechanisms for access control to the state of the random generator will most likely slow down execution.
On POSIX systems (where you seem to be) there is the
*rand48
family of functions whereerand48
,nrand48
andjrand48
take the state of the random generator as input values. So you can easily have independent states in each thread. Those you can initialize with a known number (e.g the number of your thread) and you'd have a reproducible sequence of random numbers. Or you initialize it with something non-predicable such as the current time & the number to have sequences that vary for each execution.在 Windows 上,您可以使用 rand_s() 函数,这是线程安全的。如果您已经在使用 Boost,则 boost::random 是有能力的(尽管我很欣赏这是标记为 C,而不是 C++)。
On Windows you can use the rand_s() function, which is thread safe. If you are already using Boost, then boost::random is competent (although I appreciate this is tagged C, not C++).
rand_r 是线程安全的,但也是可重入的。
下面的代码使用 xorshift 算法生成 uint128_t 伪随机数。
附加属性:
uintx_types.h:
lf.h:
rand.h:
rand.c:
test.c:
在 Linux 下使用 gcc(4.9.2) 编译。
rand_r is thread-safe but also is reentrant.
Code below generates uint128_t pseuso-random numbers using xorshift algorithm.
Additional properties:
uintx_types.h:
lf.h:
rand.h:
rand.c:
test.c:
Compile with gcc(4.9.2) under Linux.
在 Linux 系统上,您可以使用如下函数:
这里我不得不说,我真的不知道该函数生成的数字是否符合正态分布,换句话说,如果该函数是 (min,max) 范围内的有效 RNG但至少让我编写了一个需要一些随机数的简单基准。
正如您所看到的,该函数利用 POSIX 线程 ID 来重新排列随机种子。这样做,每个线程都有自己的随机种子,而不是使用取决于
time(NULL)
的全局状态On Linux systems you can use a function like:
Here I have to say that I don´t really know if numbers generated by this function fit to normal distribution in other words if this function is a valid RNG in the range (min,max) but at least worked for me to write a simple benchmark that required some random numbers.
As you can see, the function utilizes the POSIX thread id in order to re-arrange the random seed. Doing so, each thread has it own random seed instead of using global state depending on
time(NULL)