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

Best place to initialise random generator

本文关键字:最佳位置 随机 初始化      更新时间:2023-10-16

在我的程序中,我经常使用随机数生成器。我相信一般的规则是,你应该将事物定义为靠近它们被"调用"的地方,但这对随机数生成器也适用吗?

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

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);
    }

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);
    }

我想说第一个方法更快,但由于阅读了许多线程,我有点困惑,在这些线程中,它总是把所有东西都放在离调用它的地方尽可能近的地方。

在这种情况下,在循环之外创建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);
}

这与性能关系不大(尽管它可能也会表现得更好)。原因与正确性有关:

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


在性能方面,从std::random_device读取比从诸如std::mt19937之类的PRNG获取下一个值慢得多。在循环之外只做一次,将节省大量时间。此外,std::mt19937 PRNG具有大的状态(624个整数)。它根据传递给其构造函数的值生成这个初始状态。同样,只做一次会让你的表现得到提升。

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

原因是,当您将随机生成器定义定位在代码顶部时,它们将变为全局的,并且当您第一次点击"Run"按钮时,它们会自动定义。如果你在多个地方使用这些变量,这可能是最好的主意。但如果你没有,你就不需要它。因为在某些情况下,他们甚至可能不会打电话。无论如何,这个建议是针对类或方法用法的。

然而,据我所见,你将在for循环中使用这个数字,这将导致你的计算机在低于代码的情况下运行1000次。

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

这是不必要的,也是无用的。我相信您的第一个代码在性能方面会更好地工作。