3

I am having trouble with rand_r. I have a simulation that generates millions of random numbers. I have noticed that at a certain point in time, these numbers are no longer uniform. What could be the problem?

What i do: i create an instance of a generator and give it is own seed.

mainRGen= new nativeRandRUni(idumSeed_g);

here is the class/object def:

class nativeRandRUni {

    public:
        unsigned seed;

        nativeRandRUni(unsigned sd){ seed= sd; }
        float genP() { return (rand_r(&seed))/float(RAND_MAX); } // [0,1]
        int genI(int R) { return (rand_r(&seed) % R); } // [0,R-1]
};

numbers are simply generated by:

newIntNumber= mainRGen->genI(desired_max);
newFloatNumber= mainRGen->genP();

the simulations have the problem described above. I know this is happening cause i have checked the distribution of the generated numbers after the point in time that a signature is shown in the results (see this, top image, http://ubuntuone.com/0tbfidZaXfGNTfiVr3x7DR)

also, if i print the seed at t-1 and t, being t the time point of the signature, i can see the seed changing by an order of magnitude from value 263069042 to 1069048066

if i run the code with a different seed, the problem is always present but at different time points

Also, if i use rand() instead of my object, all goes well... i DO need the object cause sometimes i used threads. The example above does not have threads.

i am really lost here, any clues?

EDIT - EDIT
it can be reproducible by looping enough times, problem is that, like i said, it takes millions of iterations for the problem to arise. For seed -158342163 i get it at generation t=134065568. One can check numbers generated before (uniform) and after (not uniform). I get the same problem if i change the seed manually at given t's, see (*) in code. Something i also do not expect to happen?

#include <tr1/random>
#include <fstream> 
#include <sstream>
#include <iostream>

using std::ofstream;
using std::cout;
using std::endl;

class nativeRandRUni {

    public:
        unsigned seed;
        long count;

        nativeRandRUni(unsigned sd){ seed= sd; count=0; }
        float genP() { count++; return (rand_r(&seed))/float(RAND_MAX); } // [0,1]
        int genI(int R) { count++; return (rand_r(&seed) % R); } // [0,R-1]

};

int main(int argc, char *argv[]){

    long timePointOfProblem= 134065568;

    nativeRandRUni* mainRGen= new nativeRandRUni(-158342163);
    int rr;

    //ofstream* fout_metaAux= new ofstream();
    //fout_metaAux->open("random.numbers");
    for(int i=0; i< timePointOfProblem; i++){
            rr= mainRGen->genI(1009200);
            //(*fout_metaAux) << rr << endl;
            //if(i%1000==0) mainRGen->seed= 111111; //(*) FORCE    
    }
    //fout_metaAux->close();

}    
4

2 に答える 2

1

乱数がシミュレーションの鍵であることを考えると、独自のジェネレーターを実装する必要があります。rand_rが使用しているアルゴリズムはわかりませんが、線形合同ジェネレーターのようにかなりくだらないものである可能性があります。

基礎となるアルゴリズムを知っている場合は、高速で高品質の何かを実装することを検討します。メルセンヌツイスターの実装を検討することから始めます。

http://en.wikipedia.org/wiki/Mersenne_twister

実装が簡単で非常に高速です-分割は必要ありません。

于 2012-08-08T17:37:16.310 に答える
1

結局、ブーストから単純な解決策を試し、ジェネレーターを次のように変更しました。

class nativeRandRUni {
    public:
        typedef mt19937 EngineType;
        typedef uniform_real<> DistributionType;
        typedef variate_generator<EngineType, DistributionType> VariateGeneratorType;

        nativeRandRUni(long s, float min, float max) : gen(EngineType(s), DistributionType(min, max)) {}
        VariateGeneratorType gen;
};

私はもう問題を抱えていません...それがそれを解決したので、私はそれが何であったかを理解していないことに非常に快適に感じません。私はラファエルが正しいと思います、私はこの集中的な世代の数のためにrand_rを信頼するべきではありません

さて、これは以前より遅いので、私はそれを最適化する方法を探すかもし​​れません。 質問:メルセンヌツイスターの実装は原則としてより高速ですか?

そしてみんなに感謝します!

于 2012-08-08T22:45:51.323 に答える