在多个函数中使用相同的随机数生成器 [英] Using same random number generator across multiple functions
问题描述
我正在写一个蒙特卡洛模拟在C ++中由多次调用另一个函数(B)的主函数(A)组成,其中B中产生大量的随机数。
目前,我在B中执行以下操作:
void B(){
std ::数组< int,std :: mt19937 :: state_size> seed_data;
std :: random_device r;
std :: generate(seed_data.begin(),seed_data.end(),std :: ref(r));
std :: seed_seq seq(std :: begin(seed_data),std :: end(seed_data)); //执行热身
std :: mt19937 eng(seq);
std :: uniform_real_distribution<> RANDU(0,1);
double myRandNum = randU(eng);
//用我的随机数做一些事
}
正如你所看到的,我每次调用函数B时都会创建一个新的随机数生成器。就我所见,这是浪费时间--RNG仍然可以生成更多的随机数!
我试验过使用engextern,但是这会产生一个使用g ++的错误:
错误:'eng'has 'extern'和initializer extern std :: mt19937 eng(seq);
我怎样才能让随机数生成器为全局,以便我可以多次使用它?
小心使用一刀切的规则。 全球化是邪恶的就是其中之一。 RNG 应该是一个全局对象。 (注意:每个线程都应该有它自己的RNG!)我倾向于将我的地图封装在singleton地图中,但只需在 main()
:
std :: mt19937 rng;
int main()
{
//(种子全局对象'rng'here)
rng.dispose(10000); //对它进行热身
对于您的使用场景(每次调用产生多个RN),您不应该对每个函数调用创建一个本地分发有任何问题。
另一件事: std :: random_device
不是你的朋友 - 它可以在任何时候出于各种愚蠢的原因而随时抛出
。确保将其包装在 try
.. catch
块中。或者,我建议您使用平台特定的方式来获得真正的随机数。 (在Windows上,使用Crypto API。在其他所有方面,使用 / dev / urandom /
。)
这有助于。
I am given to believe that random number generators (RNGs) should only be seeded once to ensure that the distribution of results is as intended.
I am writing a Monte Carlo simulation in C++ which consists of a main function ("A") calling another function ("B") several times, where a large quantity of random numbers is generated in B.
Currently, I am doing the following in B:
void B(){
std::array<int, std::mt19937::state_size> seed_data;
std::random_device r;
std::generate(seed_data.begin(), seed_data.end(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); //perform warmup
std::mt19937 eng(seq);
std::uniform_real_distribution<> randU(0,1);
double myRandNum = randU(eng);
//do stuff with my random number
}
As you can see, I am creating a new random number generator each time I call the function B. This, as far as I can see, is a waste of time - the RNG can still generate a lot more random numbers!
I have experimented with making "eng" extern but this generates an error using g++:
error: ‘eng’ has both ‘extern’ and initializer extern std::mt19937 eng(seq);
How can I make the random number generator "global" so that I can use it many times?
Be careful with one-size-fits-all rules. 'Globals are evil' is one of them. A RNG should be a global object. (Caveat: each thread should get its own RNG!) I tend to wrap mine in a singleton map, but simply seeding and warming one up at the beginning of main()
suffices:
std::mt19937 rng;
int main()
{
// (seed global object 'rng' here)
rng.dispose(10000); // warm it up
For your usage scenario (generating multiple RNs per call), you shouldn't have any problem creating a local distribution for each function call.
One other thing: std::random_device
is not your friend -- it can throw
at any time for all kinds of stupid reasons. Make sure to wrap it up in a try
..catch
block. Or, and I recommend this, use a platform specific way to get a true random number. (On Windows, use the Crypto API. On everything else, use /dev/urandom/
.)
Hope this helps.
这篇关于在多个函数中使用相同的随机数生成器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!