初始化随机发生器的最佳位置

Mil*_*lan 1 c++ performance

在我的程序中,我使用了一个随机数生成器.我认为一般规则是你应该将事物定义为接近它们被"调用"的地方,但这对于随机数生成器是否也适用?

例如,在我的代码中,我可以选择:

std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(-2147483647, 2147483646);

lots of code

    for (i = 0; i < 10000; i++)
    {
        variable x = uni(rng);
    }
Run Code Online (Sandbox Code Playgroud)

要么

lots of code

    for (i = 0; i < 10000; i++)
    {
        std::random_device rd;
        std::mt19937 rng(rd());
        std::uniform_int_distribution<int> uni(-2147483647, 2147483646); 
        variable x = uni(rng);
    }
Run Code Online (Sandbox Code Playgroud)

我会说第一种方法更快,但由于阅读了很多线程,我觉得它总是将所有内容放在靠近它所调用的地方.

And*_*rew 5

在这种情况下,在循环外创建RNG 要好得多:

std::random_device rd;
std::mt19937 rng(rd());
std::uniform_int_distribution<int> uni(-2147483647, 2147483646);

for (i = 0; i < 10000; i++)
{
    variable x = uni(rng);
}
Run Code Online (Sandbox Code Playgroud)

其原因与性能无关(尽管它也可能表现更好).原因是正确性:

您每次通过循环初始化一个新的随机序列,并只读取一个值.相反,您应该只将序列初始化一次,并从中消耗许多值.在循环外部初始化,并在循环内消耗.


在性能方面,从a读取std::random_device比从PRNG中获取下一个值要慢得多std::mt19937.在循环外执行此操作只会节省大量时间.此外,std::mt19937PRNG具有大状态(624个整数).它从传递给构造函数的值生成此初始状态.再一次,这样做只会给你带来性能提升.

当然,在循环外初始化具有也是标准RNG的正确使用模型的优点.