为什么不只使用random_device? [英] Why not just use random_device?

查看:339
本文介绍了为什么不只使用random_device?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对c ++ 11随机库有些困惑.

I am a bit confused about the c++11 random library.

我的理解:我们需要两个单独的概念:

What I understand: we need two separate concepts:

  • 随机引擎(可以是伪(需要种子)或真实的)
  • 分布:它使用特定分布将从引擎获得的数字映射到特定间隔.

我不明白的是为什么不只使用这个:

What I don't understand is why not just use this:

std::random_device rd;
std::uniform_int_distribution<int> dist(1, 5);

// get random numbers with:
dist(rd);

据我所知,这很好.

相反,这是我在大多数示例/站点/文章中发现的:

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, e.g. cryptography, just your basic getting started articles.

我的怀疑是,因为std::mt19937(或std::default_random_engine)接受种子,因此在调试会话期间提供相同的种子可能更容易调试.

My suspicion is because std::mt19937 (or std::default_random_engine) accepts a seed, it can be easier to debug by providing the same seed during a debug session.

此外,为什么不只是:

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

推荐答案

此外,为什么不只是:

Also, why not just:

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

如果只执行一次,可能会很好,但是,如果多次执行,最好跟踪std::random_device而不是不必要地创建/销毁它.

It might be fine if you only will do this once, but if you will do it many times, it's better to keep track of your std::random_device and not create / destroy it unnecessarily.

查看实现std::random_device的libc ++源代码可能会有所帮助,这很简单.这只是std::fopen("/dev/urandom")上的薄薄包装.因此,每次创建std::random_device时,您都会得到另一个文件系统句柄,并支付所有相关费用.

It may be helpful to look at the libc++ source code for implementation of std::random_device, which is quite simple. It's just a thin wrapper over std::fopen("/dev/urandom"). So each time you create a std::random_device you are getting another filesystem handle, and pay all associated costs.

据我所知,在Windows上,std::random_device表示对Microsoft加密API的一些调用,因此每次执行此操作时,您都将初始化和销毁​​某些加密库接口.

On windows, as I understand, std::random_device represents some call to a microsoft crypto API, so you are going to be initializing and destroying some crypto library interface everytime you do this.

这取决于您的应用程序,但是出于一般目的,我认为这种开销始终可以忽略不计.有时候是这样,然后这很好.

It depends on your application, but for general purposes I wouldn't think of this overhead as always negligible. Sometimes it is, and then this is great.

我想这与您的第一个问题有关:

I guess this ties back into 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};

至少我的想法是:

  • std::mt19937是一个非常简单且可靠的随机生成器.它是独立的,将完全存在于您的过程中,而不会调用OS或其他任何东西.该实现由标准强制进行,至少是在boost中,它在各处都使用了相同的代码,这些代码均源自原始的mt19937论文.这段代码非常稳定,并且是跨平台的.您可以完全确信,对其进行初始化,从中进行查询等将可以在您在其上编译的任何平台上编译为类似的代码,并且您将获得类似的性能.

  • std::mt19937 is a very simple and reliable random generator. It is self-contained and will live entirely in your process, not calling out to the OS or anything else. The implementation is mandated by the standard, and at least in boost, it used the same code everywhere, derived from the original mt19937 paper. This code is very stable and it's cross-platform. You can be pretty confident that initializing it, querying from it, etc. is going to compile to similar code on any platform that you compile it on, and that you will get similar performance.

std::random_device非常不透明.您实际上并不确切地知道它是什么,它将要做什么,或者它将会有多高效.您甚至都不知道它是否可以实际获取-尝试创建它时可能会引发异常.您知道它不需要种子.通常,您不应该从中提取大量数据,而只是用它来生成种子.有时,它充当加密API的一个很好的接口,但实际上并不需要这样做,但遗憾的是,有时并不需要.它可能对应于UNIX上的/dev/random,它可能对应于/dev/urandom/.它可能对应于某些MSVC加密API(Visual Studio),或者可能只是一个固定常数(mingw).如果您为某个电话交叉编译,谁知道它会做什么. (即使您确实获得了/dev/random,仍然存在性能可能不一致的问题-它可能工作得很好,直到熵池用尽,然后运行缓慢像狗一样.)

std::random_device by contrast is pretty opaque. You don't really know exactly what it is, what it's going to do, or how efficient it will be. You don't even know if it can actually be acquired -- it might throw an exception when you attempt to create it. You know that it doesn't require a seed. You're not usually supposed to pull tons and tons of data from it, just use it to generate seeds. Sometimes, it acts as a nice interface to cryptographic APIs, but it's not actually required to do that and sadly sometimes it doesn't. It might correspond to /dev/random on unix, it might correspond to /dev/urandom/. It might correspond to some MSVC crypto API (visual studio), or it might just be a fixed constant (mingw). If you cross-compile for some phone, who knows what it will do. (And even when you do get /dev/random, you still have the problem that performance may not be consistent -- it may appear to work great, until the entropy pool runs out, and then it runs slow as a dog.)

我的想法是,std::random_device应该像是time(NULL)的种子的改进版本-这是一个很低的门槛,因为time(NULL)是考虑到所有因素的cr脚种子.我通常会在过去使用time(NULL)生成种子的地方使用它.除此之外,我真的不认为这很有用.

The way I think about it is, std::random_device is supposed to be like an improved version of seeding with time(NULL) -- that's a low bar, because time(NULL) is a pretty crappy seed all things considered. I usually use it where I would have used time(NULL) to generate a seed, back in the day. I don't really consider it all that useful outside of that.

这篇关于为什么不只使用random_device?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆