std :: random_device的线程安全性

时间:2017-02-10 10:43:48

标签: c++ c++11 random openmp

我有一些看起来有点像这样的代码:

std::random_device rd;

#pragma omp parallel
{
    std::mt19937 gen(rd());
    #pragma omp for
    for(int i=0; i < N; i++)
    {
        /* Do stuff with random numbers from gen() */
    }
}

我有几个问题:

  • std::random_device线程是否安全?即当多个线程立刻调用它时,它会做些无用的事吗?
  • 这通常是个好主意吗?我应该担心重叠的随机数流吗?
  • 有没有更好的方法来实现我想要的(每个线程中的独立随机数流 - 我现在不太担心重复性)?

如果它对我主要在Windows上运行的std::random_device的工作方式有任何影响,尽管我希望代码在Linux和OSX上同样运行良好。

2 个答案:

答案 0 :(得分:2)

并行使用随机设备不是一个好主意。即使阻塞,您可能也不会遇到重叠随机数流的麻烦,但是您可以添加一个附加的同步点。

您应该设置与要启动的线程一样多的随机数引擎(RNE), omp_get_num_threads() 。 创建RNE的std :: vector并将它们植入程序的顺序部分。对于播种,您可以使用随机设备和std::seed_seq

然后在每个线程中使用与线程号 omp_get_thread_num() 相关的RNE。

从不使用随机设备生成随机数,它的速度很慢,并且通常不会生成均匀分布的随机数!

根据所需的随机数质量,可以使用预定义的随机数生成器之一。如果您要进行蒙特卡洛模拟或加密,请特别小心选择哪种算法。

您会发现有关随机引擎的许多有用信息,网址为 https://en.cppreference.com/w/cpp/numeric/random

答案 1 :(得分:0)

在没有 WinRT 的 Windows 上,它使用 CryptGenRandom,它是线程安全的 https://stackoverflow.com/a/46171432/2024042

在带有 WinRT 的 Windows 上,它使用 CryptographicBuffer::GenerateRandom。没有关于线程安全的文档,但它似乎没有状态。因此它应该是线程安全的。

在 Linux 上,它似乎从 /dev/urandom 读取,这是线程安全的。

我从 libs/random/src/random_device.cpp 读到了这个实现。

我不知道该文件中的 _CXXRT_STD_NAME 是什么,谷歌搜索会产生 boost::random_device 作为唯一结果。也许没什么!