<random> 的线程安全使用

Thread-safe using of <random>

STL 在 his lecture on Going Native 上表示

Multiple threads cannot simultaneously call a single object.

pptx file online 上的最后一张幻灯片。)

如果我需要跨多个线程均匀分布随机数(不是独立的线程随机生成器),如何正确使用多个线程中的相同 uniform_int_distribution?或者根本不可能?

只需创建多个副本。分发是一个轻量级对象,比保护它所需的互斥锁便宜。

您还可以在定义随机生成器引擎时使用 thread_local 存储(假设您只想在程序中声明一个)。这样,每个线程都可以访问它的 "local" 副本,因此您不会有任何数据竞争。您不能只在所有线程中使用单个引擎,因为在生成序列期间更改它的状态时可能会出现数据竞争情况。

您永远不会打算使用 PRNG 足够长的时间,以至于您可以从中看到完美均匀的分布。您应该只会看到均匀分布的随机近似值。事实上,为每个线程提供自己的 PRNG 意味着每个线程需要 numThreads 倍的时间才能看到完美的分布并不重要。

PRNG 需要进行数学分析以确认它们产生每个可能的输出的次数相同,但这并不反映它们的用途。

如果以这种方式使用它们,那将代表弱点。如果你看了足够长的时间,你就会知道输出 x n 次,并且每隔 n+1 次输出,下一个输出必须是 x。这是统一的,但显然不是随机的。

真正的 RNG 永远不会产生完全一致的输出,但它也不应该两次显示相同的偏差。已知具有非均匀输出的 PRNG 每次使用时都会具有相同的非均匀输出。这意味着,如果您 运行 进行更长时间的模拟以平均掉噪声,则 PRNG 自身的偏差最终将成为最具统计意义的因素。因此,理想的 PRNG 最终应该在 足够长的周期 .

内发出完美均匀的分布(实际上通常并不完美,但在已知的非常小的范围内)

您的随机种子会在该序列中的某处随机选择一个点,并且您的随机数请求将沿着该序列进行一些处理,但是如果您发现自己一路走来走去并回到自己的起点 (甚至在该距离的 1/10 以内),那么您需要获得更大的 PRNG。

也就是说,还有一个考虑。通常专门使用 PRNG,以便可以预测其结果。

如果您处于需要互斥锁来安全访问单个 PRNG 的情况,那么您可能已经失去了可预测的行为,因为您无法判断哪个线程获得了下一个 [可预测的] 随机数.每个线程仍然看到一个不可预测的序列,因为您无法确定它得到了 PRNG 结果的哪个子集。

如果每个线程都有自己的 PRNG,那么(只要满足其他必要的排序约束)您仍然可以获得可预测的结果。