我有一些看起来有点像这样的代码:
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上同样运行良好。
答案 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 作为唯一结果。也许没什么!