2010-11-20 43 views
6

我正在写一个并行程序使用开放熔点,其中我生成随机浮点数的矩阵,然后做了一些计算。我当前想要让生成矩阵并行运行的步骤,但我有问题,rand()函数并不是要同时运行。我不想在rand上使用锁来提供互斥锁,因为这是循环中唯一要做的事情,它可能会更有效地按顺序运行它。有没有办法有效地并行执行这一步骤?并发随机数的生成

这里如果当前代码为这部分(带兰特上无互斥锁);

#pragma omp parallel default(private) 
{ 
    int i= omp_get_thread_num(); 
    for(int j=0; j<cols; j++) 
     matrix[i][j]= rand()%1000 + (float)(rand()%100)/(float)(rand()%1000); 
} 
+0

PRNG从固定的种子生成一致的数字序列。这个顺序(可重复性)对你来说很重要,还是你真的想要“随机”? – 2010-11-20 19:20:30

+0

无论他们是否按照任何特定的顺序都没关系,我遇到的问题是当我顺序运行它时,我在整个范围内获得了很好的分布,但是当我将其更改为平行时,总体上这些数字小于10,当我总结行几乎所有他们加起来0(我从来没有负面的顺序)。这使我认为函数调用存在某种并发问题。 – user381261 2010-11-20 19:28:22

+1

坚持一秒 - 平均每1000次迭代一次,rand()%1000将为零,那么如何分配呢? – TonyK 2010-11-20 19:47:22

回答

3

如果您使用C++,则应考虑使用Boost library random number classes。您可以为每个线程创建一个唯一的PRNG实例。如果您需要重复性,您可以用重复生成的种子值初始化主线程中的每个实例。

0

如果伪足够好(参见本的评论),那么你可以创建自己的PRNG(例如,一个梅森难题,而不是大多数系统使用的弱模法),并实现每一个独立的发电机线。如果你这样做,你必须确保每个发生器都有不同的种子。

0

一个真正的问题是如果你想要再现性,这在测试中经常需要。用给定的种子生成一系列线程种子。然后每个线程将使用自己的种子生成数字。

rand()不是线程安全的事实不是一个问题。有很多可用的算法,并且对于每个线程滚动一个实例(状态)是微不足道的,例如从http://en.wikipedia.org/wiki/Random_number_generation#Computational_methods开始。锁定每个rand()调用将是一个并发灾难。

3

我想你正在寻找rand_r(),它显式地将当前的RNG状态作为参数。然后每个线程应该拥有它自己的种子数据副本(无论您希望每个线程开始使用相同的种子还是不同的种子取决于您在做什么,在这里您希望它们与众不同或者您会得到相同的行一次又一次)。这里有一些关于rand_r()和线程安全的讨论:whether rand_r is real thread safe?

所以说你想让每一个线程的种子都以它的线程号开始(这可能不是你想要的,因为每次你运行相同数量的线程时它会给出相同的矩阵,为例):

#pragma omp parallel default(none) shared(matrix, cols) 
{ 
    int i= omp_get_thread_num(); 
    unsigned int myseed = i; 
    for(int j=0; j<cols; j++) 
     matrix[i][j]= rand_r(&myseed)%1000 + (float)(rand_r(&myseed)%100)/(float)(rand_r(&myseed)%1000 + 1); 
} 

现在每个线程被完全改变自己的状态(rand_r()是一个纯函数),你应该回家自由。