0

我正在使用 C++11 的random库,并且我有一个小程序可以在具有单位半径的圆上生成坐标对 x, y。这是简单的多线程程序

#include <iostream>
#include <fstream>
#include <random>

using namespace std;



int main()
{
    const double PI = 3.1415;



    double angle, radius, X, Y;
    int i;
    vector<double> finalPositionX, finalPositionY;

    #pragma omp parallel
    {
        vector <double> positionX, positionY;

        mt19937 engine(0);
        uniform_real_distribution<> uniform(0, 1);
        normal_distribution<double> normal(0, 1);



        #pragma omp for private(angle, radius, X, Y)
        for(i=0; i<1000000; ++i)
        {
            angle  = uniform(engine)*2.0*PI;
            radius = sqrt(uniform(engine));
            X      = radius*cos(angle);
            Y      = radius*sin(angle);

            positionX.push_back(X);
            positionY.push_back(Y);
        }
        #pragma omp barrier

        #pragma omp critical
        finalPositionX.insert(finalPositionX.end(), positionX.begin(), positionX.end());
        finalPositionY.insert(finalPositionY.end(), positionY.begin(), positionY.end());
    }


    ofstream output_data("positions.txt", ios::out);
    output_data.precision(9);
    for(unsigned long long temp_var=0; temp_var<(unsigned long long)finalPositionX.size(); temp_var++)
    {
        output_data << finalPositionX[temp_var]
                    << "\t\t\t\t"
                    << finalPositionY[temp_var]
                    << "\n";
    }
    output_data.close();
    return 0;
}

问题:许多 x 坐标出现两次(与 y 坐标相同)。我不明白这一点,因为周期mt19937比 1.000.000 长得多。有谁知道这里有什么问题?

注意:当我不对应用程序进行多线程处理时,我会得到相同的行为,因此问题与错误的多线程处理无关。

编辑正如其中一个答案所指出的,我不应该对两个线程使用相同的种子 - 但这是我在制定这个问题时犯的一个错误,在我的实际程序中,我似乎线程不同。

4

3 回答 3

1

正如本文(以及Stack Overflow 版主稍后发表的文章)中所述,真正的随机性并不完美分布。

良好的随机性:

在此处输入图像描述

不好的随机性:

在此处输入图像描述

我真的建议阅读这篇文章,但总结一下:RNG 必须是不可预测的,这意味着调用它 100 次不能完美地填充 10x10 网格。

于 2013-04-15T13:39:44.303 回答
1

使用代码的核心部分,我编写了这个不完美的测试,但从我可以看到分布非常均匀:

#include <iostream>
#include <fstream>
#include <random>
#include <map>
#include <iomanip>

using namespace std;

int main()
{
    int i;
    vector<double> finalPositionX, finalPositionY; 
    std::map<int, int> hist;


    vector <double> positionX, positionY;

    mt19937 engine(0);
    uniform_real_distribution<> uniform(0, 1);
    //normal_distribution<double> normal(0, 1);
    for(i=0; i<1000000; ++i)
    {
        double rnum = uniform(engine);            

       ++hist[std::round(1000*rnum)];

    }

    for (auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }

    return 0;
}

正如其他人已经说过的那样,看到一些重复值并不意外。对于normal发行版,我使用了以下修改rnumhist测试它,它看起来也不错:

double rnum = normal(engine);                  
++hist[std::round(10*rnum)];
于 2013-04-15T13:46:33.387 回答
0

首先 - 仅仅因为您两次获得相同的数字并不意味着它不是随机的。如果你掷骰子六次,你会期待六种不同的结果吗?参见生日悖论。话虽如此 - 你是对的,在这种特殊情况下你不应该看到太多重复。

我不熟悉“#pragma omp parallel”,但我猜你正在生成多个线程,这些线程都使用相同的种子 (0) 为 mt19937 播种。您应该为所有线程使用不同的种子 - 例如线程 ID。

于 2013-04-15T13:38:17.233 回答