我已经读过,为了确保线程安全,可以方便地将RNG
种植到并行区域内,如下所示:
int seedbase = 392872;
#pragma omp parallel
{
srand(omp_get_thread_id * seedbase);
#pragma omp for
....
}
但是如果我的并行化部分在另一个循环中呢?如果我有这样的情况:
int seedbase = 392872;
for(int i=0; i<100; ++i)
{
#pragma omp parallel
{
srand(omp_get_thread_id * seedbase);
#pragma omp for
....
}
}
我应该在哪里初始化RNG
?
答案 0 :(得分:1)
我已经读过,为了确保线程安全,可以方便地将RNG播种到并行区域内,如下所示:
尽管方便,但您的技术并非有效。无论您在何处调用srand()
,标准rand()
函数都不能成为线程安全的。它依赖于在每次调用时修改的内部静态数据,因此如果您在没有某种同步的情况下从多个线程调用它(或srand()
),那么您就会创建数据竞争。
POSIX一度定义了一个函数rand_r()
。如果你有它那么它将满足你的目的,但它现在已被标记为过时。正确使用rand_r()
与OpenMP将涉及在并行区域内建立一个私有(OpenMP sense)变量来保存种子。在每个线程中以不同或相同的方式初始化它,具体取决于您是否希望在每个线程中使用相同的随机数序列。然后,将指向该变量的指针作为参数传递给rand_r()
。在每次调用之后,您可能希望将返回值或从其派生的内容作为新种子。