C++ 如何使用OpenMP以线程安全的方式生成随机数
在并行化之前,我在循环外创建了一个C++ 如何使用OpenMP以线程安全的方式生成随机数,c++,multithreading,random,openmp,C++,Multithreading,Random,Openmp,在并行化之前,我在循环外创建了一个default\u random\u engine对象,因为创建这样的对象并不便宜。我在循环中重复使用它 当与OpenMP并行时,我注意到uniform\u dist(engine)对随机引擎进行可变引用,我认为随机引擎不是线程安全的。 程序没有崩溃,但我担心它的正确性 我假设random\u device是线程安全的,因此我可以将default\u random\u engine的定义移动到循环中,但我不想每次迭代都创建一个随机引擎对象,因为我读到了这一点并不
default\u random\u engine
对象,因为创建这样的对象并不便宜。我在循环中重复使用它
当与OpenMP
并行时,我注意到uniform\u dist(engine)
对随机引擎进行可变引用,我认为随机引擎不是线程安全的。
程序没有崩溃,但我担心它的正确性
我假设random\u device
是线程安全的,因此我可以将default\u random\u engine
的定义移动到循环中,但我不想每次迭代都创建一个随机引擎对象,因为我读到了这一点并不便宜
我认为另一种方法是创建default\u random\u engine
对象的数组(大小:线程数),并在每次迭代开始时根据线程ID使用OpenMP函数选择正确的对象
有更好的办法吗
#include <iostream>
#include <random>
using namespace std;
int main() {
int N = 1000;
vector<int> v(N);
random_device r;
default_random_engine engine(r());
#pragma omp parallel for
for (int i = 0; i < N; ++i) {
uniform_int_distribution<int> uniform_dist(1, 100);
// Perform heavy calculations
v[i] = uniform_dist(engine); // I assume this is thread unsafe
}
return 0;
}
#包括
#包括
使用名称空间std;
int main(){
int N=1000;
向量v(N);
随机_装置r;
默认的随机引擎(r());
#pragma-omp并行
对于(int i=0;i
由于实际代码将随机引擎传递给许多函数(每个函数从不同的分布生成整数和实数),因此我选择了每个线程的生成器数组,因为它对代码库的更改最少:
#include <iostream>
#include <omp.h>
#include <vector>
#include <random>
using namespace std;
int main() {
random_device r;
std::vector<std::default_random_engine> generators;
for (int i = 0, N = omp_get_max_threads(); i < N; ++i) {
generators.emplace_back(default_random_engine(r()));
}
int N = 1000;
vector<int> v(N);
#pragma omp parallel for
for (int i = 0; i < N; ++i) {
// Get the generator based on thread id
default_random_engine& engine = generators[omp_get_thread_num()];
// Perform heavy calculations
uniform_int_distribution<int> uniform_dist(1, 100);
v[i] = uniform_dist(engine); // I assume this is thread unsafe
}
return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main(){
随机_装置r;
向量发生器;
对于(int i=0,N=omp_get_max_threads();i
请记住,此代码假定程序中从未调用函数omp\u set\u num\u threads
。如果发生这种情况,线程将可能获得比旧的omp\u get\u thread\u num()
更大的编号(omp\u get\u thread\u num()
),这将导致缓冲区溢出错误
不幸的是,此解决方案假定了标准不要求的实现细节。是的,每个线程都需要一个单独的生成器实例。请查看幻灯片132。。。查看xoroshiro128+()