我正在使用open mp编写并行程序,其中我生成一个随机浮点数矩阵,然后对其进行大量计算。我目前想要生成并行运行矩阵的步骤,但我遇到的问题是rand()函数并不意味着并发运行。我不想使用锁来在rand上提供互斥,因为这是在循环中唯一做的事情,它可能只是更有效地顺序运行它。有没有办法有效地并行完成这一步?
这里是这个部分的当前代码(在rand上没有mutex);
#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 :(得分: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()是一个纯函数),你应该回家了。
答案 1 :(得分:3)
如果您使用的是C ++,则应考虑使用Boost library random number classes。您可以为每个线程创建唯一的PRNG实例。如果需要可重复性,可以使用可重复生成的种子值初始化主线程中的每个实例。
答案 2 :(得分:0)
如果伪随机足够好(参见Ben的评论),那么你可以创建自己的PRNG(例如A Mersenne Twister而不是大多数系统使用的弱模数方法),并为每个线程实现一个独立的生成器。如果你这样做,你必须确保每个发电机都有不同的种子。
答案 3 :(得分:0)
一个真正的问题是,如果你想要重复性,这在测试中经常需要。使用给定的种子生成一系列线程种子。然后每个线程将使用自己的种子来生成数字。
rand()
不是线程安全的事实不是问题。有很多可用的算法,并且每个线程滚动一个实例(状态)是微不足道的,例如从http://en.wikipedia.org/wiki/Random_number_generation#Computational_methods开始。锁定每个rand()
调用将是并发灾难。