Bil*_*ean 7 c++ random openmp c++11
我在C++ 11中使用新的随机数生成器.尽管存在不同的意见,但从这个主题看来,大多数人认为它们不是线程安全的.因此,我想制作一个程序,每个线程使用自己的RNG.
在如何使用OpenMP实现此目的的相关讨论中给出了一个示例:
#include <random>
#include <iostream>
#include <time.h>
#include "omp.h"
using namespace std;
int main()
{
    unsigned long long app = 0;
    {
        //mt19937_64 engine((omp_get_thread_num() + 1)); //USE FOR MULTITHREADING
        mt19937_64 engine; //USE FOR SINGLE THREAD
        uniform_real_distribution<double> zeroToOne(0.0, 1.0);
        //#pragma omp parallel for reduction(+:app) //USE FOR MULTITHREADING
        for (unsigned long long i = 0; i < 2000000000; i++)
        {
            if(zeroToOne(engine) < 0.5) app++;
        }
    }
    cout << app << endl;
    return 0;
}
当我运行该程序的多线程和单线程版本并跟踪时间时,执行后需要相同的时间才能完成.此外,app两种情况下的大小不一样,但我怀疑这仅仅是因为种子不同.
问题:提供的示例是否正确显示了如何强制每个线程使用自己的RNG?如果没有,我可以看一个如何完成这个的例子,或者参考一些他们解释如何实现这个目的的地方?
您不得在多个线程之间共享随机引擎的实例.您应该锁定单个引擎或为每个线程创建一个引擎(使用不同的种子(请注意e4e5f4关于创建并行MT引擎的答案)).在OpenMP的情况下,您可以轻松地将每个线程中的一个引擎存储在一个向量中,并通过其结果omp_get_thread_num()位于0和之间来检索它omp_get_num_threads()–1.
class RNG
{
public:
    typedef std::mt19937 Engine;
    typedef std::uniform_real_distribution<double> Distribution;
    RNG() : engines(), distribution(0.0, 1.0)
    {
        int threads = std::max(1, omp_get_max_threads());
        for(int seed = 0; seed < threads; ++seed)
        {
            engines.push_back(Engine(seed));
        }
    }
    double operator()()
    {
        int id = omp_get_thread_num();
        return distribution(engines[id]);
    }
    std::vector<Engine> engines;
    Distribution distribution;
};
int main()
{
     RNG rand;
     unsigned long app = 0;
     #pragma omp parallel for reduction(+:app)
     for (unsigned long long i = 0; i < 2000000000; i++)
     {
         if(rand() < 0.5) app++;
     }
}