代码之家  ›  专栏  ›  技术社区  ›  njvb

并发随机数生成

  •  6
  • njvb  · 技术社区  · 14 年前

    我正在编写一个使用open mp的并行程序,在这个程序中,我生成一个随机浮点数矩阵,然后对它进行一些计算。我现在想在生成矩阵的步骤中并行运行,但是我有一个问题,rand()函数并不打算并发运行。我不想使用锁在rand上提供互斥,因为这是循环中唯一要做的事情,而且按顺序运行它可能更高效。是否有任何方法可以同时有效地完成这一步骤?

    如果此部分的当前代码(RAND上有out 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);
    }
    
    4 回复  |  直到 14 年前
        1
  •  3
  •   andand    14 年前

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

        2
  •  3
  •   Community Michael Schmitz    7 年前

    我认为您正在寻找rand_r(),它显式地将当前的rng状态作为参数。然后每个线程都应该有它自己的种子数据副本(您是否希望每个线程以相同的种子开始,还是以不同的种子开始取决于您在做什么,这里您希望它们不同,或者您将一次又一次获得相同的行)。这里有一些关于r and_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);
    }
    

    现在,每个线程都在专门修改自己的状态(r and_r()是一个纯函数),您应该可以在家中自由使用。

        3
  •  0
  •   winwaed    14 年前

    如果伪随机足够好(参见Ben的评论),那么您可以创建自己的prng(例如mersenne twister,而不是大多数系统使用的弱模方法),并为每个线程实现一个独立的生成器。如果这样做,必须确保每个生成器都有不同的种子。

        4
  •  0
  •   Remus Rusanu    14 年前

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

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