Why not just use random_device?

I am a bit confused in the random C ++ 11 library.

What I understand: we need two separate concepts:

  • random engine (which can be pseudo (you need a seed) or real)
  • : It displays the numbers received from the engine at a specific interval using a specific distribution.

I do not understand why not just use this:

std::random_device rd; std::uniform_int_distribution<int> dist(1, 5); // get random numbers with: dist(rd); 

As far as I can tell, this works well.

Instead, this is what I found on most examples / sites / articles:

 std::random_device rd; std::mt19937 e{rd()}; // or std::default_random_engine e{rd()}; std::uniform_int_distribution<int> dist{1, 5}; // get random numbers with: dist(e); 

I am not talking about special use, for example. cryptography, just your main startup article.

My suspicion is that std::mt19937 (or std::default_random_engine ) accepts the seed, it can be more easily debugged by providing the same seed during a debugging session.

Also, why not just:

 std::mt19937 e{std::random_device{}()}; 
+17
c ++ random c ++ 11
source share
2 answers

Also, why not just:

std::mt19937 e{std::random_device{}()};

It may be good if you only do it once, but if you do it many times, it is better to keep track of your std::random_device , rather than creating / destroying it unnecessarily.

It may be useful to look at the source code of libC ++ for the implementation of std::random_device , which is pretty simple. This is just a thin wrapper over std::fopen("/dev/urandom") . Therefore, every time you create std::random_device , you get a different file system descriptor and pay all the associated costs.

On Windows, as I understand it, std::random_device is some std::random_device microsoft crypto API call, so you will initialize and destroy some cryptographic program library interface every time you do it.

It depends on your application, but for general purposes I would not think about this overhead, as always, negligible. Sometimes it is, and then it’s great.

I think this is related to your first question:

Instead, this is what I found on most examples / sites / articles:

  std::random_device rd; std::mt19937 e{rd()}; // or std::default_random_engine e{rd()}; std::uniform_int_distribution<int> dist{1, 5}; 

At least I think about it:

  • std::mt19937 is a very simple and reliable random generator. The implementation is obliged by the standard, and, at least in boost, it everywhere used the same code obtained from the original article mt19937 . This code is very stable and cross-platform. You can be sure that initialization, a request from it, etc. You are going to compile similar code on any platform on which you compile it, and that you will get the same performance.

  • std::random_device contrast, is pretty opaque. You really do not know exactly what it is, what it is going to do, or how effective it will be. You don’t even know if it can really be received - it can throw an exception when you try to create it. You know that this does not require seed. Usually you should not extract tons and tons of data from it, just use them to generate seeds. Sometimes it acts as a good interface for cryptographic APIs, but in fact it is not required, and, unfortunately, sometimes it is not. It can match /dev/random on unix, it can match /dev/urandom/ . It may correspond to some cryptographic API MSVC (visual studio), or it may just be a fixed constant (mingw). If you cross-compile a phone, who knows what it will do. (And even if you get /dev/random , you still have a problem that performance can be consistent - it might seem like it works fine until the entropy pool runs out, and then it runs slowly, like a dog.)

As I think of it, std::random_device should look like an improved version of the sowing with time(NULL) - a low bar, because time(NULL) is a pretty crappy seed, everything considered. I usually use it, where I would use time(NULL) to generate the seed for the day. I really don't find all this useful outside of this.

+20
source share

This article is a good point to start.

I am going to synthesize just a few points:

  • It has an unknown value.

    How expensive is it to read the number from this β€œdevice”? This is unspecified. For example, it could be reading from / dev / random on a Linux system, which could block a long waiting period for entropy (which in itself is a problem for various reasons).

For my personal experience, I have notified that std::random_device usually slower than a simple pseudo-random algorithm. In general, this may not be true, but this usually happens. This is because it may include physical devices or other equipment than a simple processor.

  • In fact, this can be deterministic.

    C ++ 11 std :: random_device is not required to be non-deterministic! Implementations can and do implement it as a simple RNG with a fixed seed, so it produces the same output for each program run.

+8
source share

All Articles