-1

I need to generate uniform random numbers in a for loop. for loop goes for 1000000 numbers. There is another for loop which goes to 2000 inside it. So I generate 2*10^9 uniform random numbers. I use below method:

#include <random>
    double zeta;
     unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
        auto uniform_rand = bind(uniform_real_distribution<double>(0,1), mt19937(seed)); 
    for(int j=0; j<1000000; j++)
               for(int i=0; i<2000; i++) 
       zeta=-eta/2.0+uniform_rand()*eta; // in the range (-eta/2, +eta/2)
theta[i]+=zeta;
    end
end
Oliver Range
  • 365
  • 3
  • 10

2 Answers2

1

It's almost the same as yours. I just don't see any need for a binder or a lambda.

EDIT: I also changed the generator from mt19937 to minstd_rand which has made the code 88 times faster. With mt19937 the code has aproximately the same performance as the one in the question.

#include <random>

int main() {
    /*std::mt19937 gen(std::random_device{}());*/
    // Changing mt19937 to minstd_rand makes the code run 88 times faster!
    std::minstd_rand gen(std::random_device{}());
    std::uniform_real_distribution<double> dist(0, 1);
    for(unsigned int i = 0; i < 1000000; ++i) {
        for(unsigned int j = 0; j < 2000; ++j) {
            double anotherRandomNumber = dist(gen);
            // Do whatever you want with generated random number.
        }
    }
}
navyblue
  • 776
  • 4
  • 8
  • Is it really faster than what I have written? – Oliver Range Oct 17 '17 at 17:32
  • Does it create different random numbers in different runs? – Oliver Range Oct 17 '17 at 17:33
  • @OliverRange yes, it seeds the random generator each time with `std::random_device`. But sometimes it won't work, see https://stackoverflow.com/questions/18880654/why-do-i-get-the-same-sequence-for-every-run-with-stdrandom-device-with-mingw – Mark Ransom Oct 17 '17 at 17:41
  • @OliverRange `std::random_device` will use a genuinely non deterministic random device if your platform has one. That means pretty much all desktop operating systems. The one problem is that `GCC MinGW` compiler on windows has a bug so it doesn't work on that specific compiler (yet). – Galik Oct 17 '17 at 17:48
  • @OliverRange Yes, it is just one Windows compiler that has the bug. – Galik Oct 17 '17 at 17:51
  • no match for call to ‘(std::uniform_real_distribution) (double&, double&, double&, double&, double&)’ It doesn't run @Galik – Oliver Range Oct 17 '17 at 18:13
  • @OliverRange The code in this answer runs for me. Did you type it in exactly as shown? – Galik Oct 17 '17 at 18:21
  • The error message suggests that you're doing something really strange. It seems that you're calling `dist` with x[i], y[i], x[*itp] etc. Make sure you call it exactly like I did in may answer. That is you can only call `dist` giving it a generator as the argument; in this case `gen`. – navyblue Oct 21 '17 at 17:52
  • Is it better to put std::minstd_rand gen(std::random_device{}()); std::uniform_real_distribution dist(0, 1); outside of the main fuction or not? – Oliver Range Oct 23 '17 at 09:10
  • It's too general a question to answer it. However, if you mean this particular piece of code that I've written as the answer then you shouldn't move `gen` or `dist` out of the `main` function because that would make this simple program overcompilcated or you would declare them as global variables which wouldn't make the code any better. – navyblue Oct 23 '17 at 14:17
0

Use this algorithm from here:

uint64_t s[2] = { 0x41, 0x29837592 };

static inline uint64_t rotl(const uint64_t x, int k) {
    return (x << k) | (x >> (64 - k));
}

uint64_t next(void) {
    const uint64_t s0 = s[0];
    uint64_t s1 = s[1];
    const uint64_t result = s0 + s1;

    s1 ^= s0;
    s[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14); // a, b
    s[1] = rotl(s1, 36); // c

    return result;
}

double uniform() {
    return next()*(1.0/18446744073709551616.0);
}

This is 4 times faster than your example on my machine.

Note: you need to seed s, perhaps with std::random_device.

geza
  • 28,403
  • 6
  • 61
  • 135