I wrote a program in Fortran that uses RANDOM_NUMBER() and was compiled with gfortran, but I noticed that the generated random numbers are inconsistent between versions. If RANDOM_SEED() is not used to seed the random number generator, then both, gfortran 4.4.7 (default in Centos 6) and gfortran 4.8.5 (default in Centos 7) produce the same sequence of random numbers. It surprises me because the default seed in gfortran 4.4.7 is 8 integers long while the default seed in gfortran 4.8.5 is 12 integers long and the numbers are completely different, but still the random number sequence is the same. On the other hand gfortran 7.3.1 (included in the devtoolset7 package in Centos 7) produces a different sequence of random numbers on every run unless it is initialized with RANDOM_SEED(). However the seed in this version consist of 33 integer numbers and therefore the seeds of the older versions will not work.
For reproducibility I need to reproduce exactly the same random number sequence on every run regardless of the gfortran version. I would like to know if there is a way to translate the default seed among different gfortran versions or if there is any other way to get the same random number sequence with any gfortran version.
No, for GFortran 7 the PRNG algorithm was changed to a completely different kind of algorithm. There's basically no way to get an identical stream of random numbers for GFortran <7 and >= 7.
If you need exact reproducibilty across different GFortran version you need to use another PRNG implementation.
Janneb is correct.
If you need consistency between compiler versions, and perhaps even compilers (ifort, pgfortran), you should use something other than the built-in tool. I am personally aware of SPRNG (http://www.sprng.org/), and there are presumably many other similar tools.
Related
I use the following code to test the C++ <random> library.
Why do I get the exact same sequence for every run of the compiled executable? Is rd() deterministic upon compilation? How do I get different output for each run?
GCC 4.8.1 on Windows 7 64bit. Using MinGW distribution from http://nuwen.net/mingw.html.
EDIT: I tested the same piece code with Visual Studio. There is no problem. The outputs are non deterministic. This could be a bug in mingw gcc 4.8.1 that I used.
#include <iostream>
#include <random>
using namespace std;
int main(){
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int> dist(0,99);
for (int i = 0; i< 16; ++i){
cout<<dist(mt)<<" ";
}
cout <<endl;
}
From http://en.cppreference.com/w/cpp/numeric/random/random_device:
Note that std::random_device may be implemented in terms of a pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation.
I would expect a decent implementation to at least seed the RNG though.
Edit: I suspect they deliberately chose to deliver the same sequence each time, to make obvious the fact that the stream wasn't as random as promised.
I got a confirmed answer from STL from MSFT:
Unlike VC, GCC hasn't implemented random_device nondeterministically on Windows. Boost has, so you can use Boost.Random.
This is a GCC bug, fixed in GCC 9.2.
If you have this problem, update your compiler. (You can get a fresh GCC from MSYS2, for example.)
You may need to pass a parameter to the constructor:
https://gcc.gnu.org/onlinedocs/gcc-4.9.1/libstdc++/api/a00899.html
GCC does not implement rd.entropy() correctly - it always returns 0 (at least on Mac OS X).
Unfortunately, there seems to be no way to mix additional entropy into random_device, which matters because it usually/often (look at Linux /dev/random and /dev/urandom, and at the Intel RDRAND implementation) implements a pseudo-random number generator under the hood. I'd like to be able to improve its output by injecting something I consider random to mix with whatever its entropy source produces. Again, since this device (or kernel module) internally implements a cryptographic algorithm for processing the entropy bits it obtains to generate its output, I'd like to be able to "randomize" that process more by injecting my own data to mix with whatever entropy that device picks.
For example, consider Java SecureRandom(). It does not allow you to set the seed (which indeed would convert it to PRNG), but it would happily mix what you provide with whatever it is using to "randomize" its output even more.
I personally prefer RDRAND. A small assembly library with a compact C interface. Here are the references:
David Johnson from Intel explains RDRAND on Stackoverflow
Stackoverflow pointers to RDRAND library source for Windows, Linux, and Mac OS X
Intel blog on RDRAND library, and a download link
I use the following code to test the C++ <random> library.
Why do I get the exact same sequence for every run of the compiled executable? Is rd() deterministic upon compilation? How do I get different output for each run?
GCC 4.8.1 on Windows 7 64bit. Using MinGW distribution from http://nuwen.net/mingw.html.
EDIT: I tested the same piece code with Visual Studio. There is no problem. The outputs are non deterministic. This could be a bug in mingw gcc 4.8.1 that I used.
#include <iostream>
#include <random>
using namespace std;
int main(){
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int> dist(0,99);
for (int i = 0; i< 16; ++i){
cout<<dist(mt)<<" ";
}
cout <<endl;
}
From http://en.cppreference.com/w/cpp/numeric/random/random_device:
Note that std::random_device may be implemented in terms of a pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation.
I would expect a decent implementation to at least seed the RNG though.
Edit: I suspect they deliberately chose to deliver the same sequence each time, to make obvious the fact that the stream wasn't as random as promised.
I got a confirmed answer from STL from MSFT:
Unlike VC, GCC hasn't implemented random_device nondeterministically on Windows. Boost has, so you can use Boost.Random.
This is a GCC bug, fixed in GCC 9.2.
If you have this problem, update your compiler. (You can get a fresh GCC from MSYS2, for example.)
You may need to pass a parameter to the constructor:
https://gcc.gnu.org/onlinedocs/gcc-4.9.1/libstdc++/api/a00899.html
GCC does not implement rd.entropy() correctly - it always returns 0 (at least on Mac OS X).
Unfortunately, there seems to be no way to mix additional entropy into random_device, which matters because it usually/often (look at Linux /dev/random and /dev/urandom, and at the Intel RDRAND implementation) implements a pseudo-random number generator under the hood. I'd like to be able to improve its output by injecting something I consider random to mix with whatever its entropy source produces. Again, since this device (or kernel module) internally implements a cryptographic algorithm for processing the entropy bits it obtains to generate its output, I'd like to be able to "randomize" that process more by injecting my own data to mix with whatever entropy that device picks.
For example, consider Java SecureRandom(). It does not allow you to set the seed (which indeed would convert it to PRNG), but it would happily mix what you provide with whatever it is using to "randomize" its output even more.
I personally prefer RDRAND. A small assembly library with a compact C interface. Here are the references:
David Johnson from Intel explains RDRAND on Stackoverflow
Stackoverflow pointers to RDRAND library source for Windows, Linux, and Mac OS X
Intel blog on RDRAND library, and a download link
I've a code when I run in visual studio, I get different results and when I run using g++ compiler I get different results. It has a seed of 1, so I guess this should not affect it, Also there are some parts of the code which run in thread(but this part doesn't contain any rand function)
I get the same results by running the application on the same platform , but different if I use different compilers
For all behaviour that the standard defines, programs generated by all compilers must behave the same way.
For all behaviour that the standard leaves unspecified, compilers do not need to behave the same. The standard makes no guarantees about programs that violate the standard for example. The standard also leaves many details up to the implementation.
Also, compilers tend to not always comply to the standard in all cases and some compilers may not support same version of the standard as another.
Finally, some standard rules are found to be ambiguous, and different compilers may have chosen an opposite interpretation. These should be documented as defect reports.
.. seed ... rand function ...
The random sequence produced by rand is implementation defined. Yes, the results can be different with different compilers.
C++11 introduced <random> header. Of the random number generators defined there, default_random_engine is the only one that has implementation defined behaviour.
If you want a reproducible pseudo-random numbers, use the C++ facilities instead, so you can choose a well-defined generator.
The C pseudo-random-number generator isn't guaranteed to be the same across compilers or platforms.
Pseudo-random number generation is a very tough problem. It is better to use a third party library. For example, there are several random number generators included with the GNU Scientific Library (https://www.gnu.org/software/gsl/). When I need a reproducible random number generator I tend to use the Mersenne Twister which is the GSL default.
Random number generation for cryptography is done with other libraries.
Also you can test the quailty of you generator is using Die Harder II (https://www.phy.duke.edu/~rgb/General/dieharder.php). And yes, technically you cannot tell how random something is, but if you can find a pattern in it - it is definitely not random.
I use the following code to test the C++ <random> library.
Why do I get the exact same sequence for every run of the compiled executable? Is rd() deterministic upon compilation? How do I get different output for each run?
GCC 4.8.1 on Windows 7 64bit. Using MinGW distribution from http://nuwen.net/mingw.html.
EDIT: I tested the same piece code with Visual Studio. There is no problem. The outputs are non deterministic. This could be a bug in mingw gcc 4.8.1 that I used.
#include <iostream>
#include <random>
using namespace std;
int main(){
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int> dist(0,99);
for (int i = 0; i< 16; ++i){
cout<<dist(mt)<<" ";
}
cout <<endl;
}
From http://en.cppreference.com/w/cpp/numeric/random/random_device:
Note that std::random_device may be implemented in terms of a pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation.
I would expect a decent implementation to at least seed the RNG though.
Edit: I suspect they deliberately chose to deliver the same sequence each time, to make obvious the fact that the stream wasn't as random as promised.
I got a confirmed answer from STL from MSFT:
Unlike VC, GCC hasn't implemented random_device nondeterministically on Windows. Boost has, so you can use Boost.Random.
This is a GCC bug, fixed in GCC 9.2.
If you have this problem, update your compiler. (You can get a fresh GCC from MSYS2, for example.)
You may need to pass a parameter to the constructor:
https://gcc.gnu.org/onlinedocs/gcc-4.9.1/libstdc++/api/a00899.html
GCC does not implement rd.entropy() correctly - it always returns 0 (at least on Mac OS X).
Unfortunately, there seems to be no way to mix additional entropy into random_device, which matters because it usually/often (look at Linux /dev/random and /dev/urandom, and at the Intel RDRAND implementation) implements a pseudo-random number generator under the hood. I'd like to be able to improve its output by injecting something I consider random to mix with whatever its entropy source produces. Again, since this device (or kernel module) internally implements a cryptographic algorithm for processing the entropy bits it obtains to generate its output, I'd like to be able to "randomize" that process more by injecting my own data to mix with whatever entropy that device picks.
For example, consider Java SecureRandom(). It does not allow you to set the seed (which indeed would convert it to PRNG), but it would happily mix what you provide with whatever it is using to "randomize" its output even more.
I personally prefer RDRAND. A small assembly library with a compact C interface. Here are the references:
David Johnson from Intel explains RDRAND on Stackoverflow
Stackoverflow pointers to RDRAND library source for Windows, Linux, and Mac OS X
Intel blog on RDRAND library, and a download link
I use the following code to test the C++ <random> library.
Why do I get the exact same sequence for every run of the compiled executable? Is rd() deterministic upon compilation? How do I get different output for each run?
GCC 4.8.1 on Windows 7 64bit. Using MinGW distribution from http://nuwen.net/mingw.html.
EDIT: I tested the same piece code with Visual Studio. There is no problem. The outputs are non deterministic. This could be a bug in mingw gcc 4.8.1 that I used.
#include <iostream>
#include <random>
using namespace std;
int main(){
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int> dist(0,99);
for (int i = 0; i< 16; ++i){
cout<<dist(mt)<<" ";
}
cout <<endl;
}
From http://en.cppreference.com/w/cpp/numeric/random/random_device:
Note that std::random_device may be implemented in terms of a pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation.
I would expect a decent implementation to at least seed the RNG though.
Edit: I suspect they deliberately chose to deliver the same sequence each time, to make obvious the fact that the stream wasn't as random as promised.
I got a confirmed answer from STL from MSFT:
Unlike VC, GCC hasn't implemented random_device nondeterministically on Windows. Boost has, so you can use Boost.Random.
This is a GCC bug, fixed in GCC 9.2.
If you have this problem, update your compiler. (You can get a fresh GCC from MSYS2, for example.)
You may need to pass a parameter to the constructor:
https://gcc.gnu.org/onlinedocs/gcc-4.9.1/libstdc++/api/a00899.html
GCC does not implement rd.entropy() correctly - it always returns 0 (at least on Mac OS X).
Unfortunately, there seems to be no way to mix additional entropy into random_device, which matters because it usually/often (look at Linux /dev/random and /dev/urandom, and at the Intel RDRAND implementation) implements a pseudo-random number generator under the hood. I'd like to be able to improve its output by injecting something I consider random to mix with whatever its entropy source produces. Again, since this device (or kernel module) internally implements a cryptographic algorithm for processing the entropy bits it obtains to generate its output, I'd like to be able to "randomize" that process more by injecting my own data to mix with whatever entropy that device picks.
For example, consider Java SecureRandom(). It does not allow you to set the seed (which indeed would convert it to PRNG), but it would happily mix what you provide with whatever it is using to "randomize" its output even more.
I personally prefer RDRAND. A small assembly library with a compact C interface. Here are the references:
David Johnson from Intel explains RDRAND on Stackoverflow
Stackoverflow pointers to RDRAND library source for Windows, Linux, and Mac OS X
Intel blog on RDRAND library, and a download link