Openmp for循环,种子随机数发生器在哪里?

问题描述:

我读过,为了保证线程安全,它的方便种子并行区域内的RNG这样的:Openmp for循环,种子随机数发生器在哪里?

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

因此,您希望每次迭代都创建一组加入其末尾的线程? – StoryTeller

+0

是的,因为外部循环范围可能非常小,所以,假设我有8个线程,如果我把它放在它之前,并且循环范围是(0,3),那么我不会让所有线程都工作,而在这种情况下,因为我的内循环肯定大于8,我相信我得到所有线程工作 –

+0

相关:[从多个线程使用stdlib的rand()](http://stackoverflow.com/q/6161322/2402272)。 –

我读过,为了保证线程安全,它的方便,播种RNG并行区域内是这样的:

便利尽管如此,你的技术是不是有效。不管您拨打srand()的哪个位置,标准rand()函数都不能成为线程安全的。它依赖于每次调用都会修改的内部静态数据,所以如果您从多个线程调用它(或srand())而没有进行某种同步,则会因此创建数据竞争。

一次,POSIX定义了一个函数rand_r()。如果你有这个,那么它会符合你的目的,但它现在已被标记为过时。在OpenMP中正确使用rand_r()将涉及在并行区域内部建立私有(OpenMP感知)变量来保存种子。根据每个线程中是否需要相同的随机数序列,在每个线程中以不同或相同方式对其进行初始化。然后将一个指向该变量的指针作为参数传递给rand_r()。在每次调用之后,您可能想要将返回值或从中派生出来的东西作为新种子。

+0

如果rand_r现在已过时,标准)功能,我应该打电话吗? –

+0

这取决于您正在编程的平台。虽然它已经过时,但不会直接替代'rand_r()',并且在可预见的将来实现实际上不可能将其删除。无论如何,你可以考虑使用它。另外,如果你只需要支持基于glibc的系统,那么还有'random_r()'和一个伴随的'srandom_r()'。 –