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

时间:2016-05-16 08:44:37

标签: 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);
    }

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

我想说第一种方法更快,但由于阅读了很多线程,我觉得它总是把所有东西放在靠近它所调用的地方。我有点困惑。

2 个答案:

答案 0 :(得分: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);
}

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

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

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

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

答案 1 :(得分:3)

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

但是,从我看到的情况来看,您将在for循环中使用该数字,这将导致您的计算机在代码下运行1000次。

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

这是不必要的,也没用。我相信你的第一个代码在性能方面会更好。