我在写大都会蒙特卡罗模拟代码。由于模拟时间很长,我想认真考虑一下在[0, 1]
中生成随机数的性能。
因此,我决定通过以下代码检查两个方法的性能:
#include <cfloat>
#include <chrono>
#include <iostream>
#include <random>
int main()
{
constexpr auto Ntry = 5000000;
std::mt19937 mt(123);
std::uniform_real_distribution<double> dist(0.0, std::nextafter(1.0, DBL_MAX));
double test1, test2;
// method 1
auto start1 = std::chrono::system_clock::now();
for (int i=0; i<Ntry; i++) {
test1 = dist(mt);
}
auto end1 = std::chrono::system_clock::now();
auto elapsed1 = std::chrono::duration_cast<std::chrono::microseconds>(end1-start1).count();
std::cout << elapsed1 << std::endl;
// method 2
auto start2 = std::chrono::system_clock::now();
for (int i=0; i<Ntry; i++) {
test2 = 1.0*mt() / mt.max();
}
auto end2 = std::chrono::system_clock::now();
auto elapsed2 = std::chrono::duration_cast<std::chrono::microseconds>(end2-start2).count();
std::cout << elapsed2 << std::endl;
}
结果是
据我所知,有许多帖子推荐使用std::uniform_real_distribution
。但是从性能上看,使用后者是很有诱惑力的,正如这个结果所示。
你能告诉我使用std::uniform_real_distribution
有什么意义吗?使用1.0*mt() / mt.max()
的缺点是什么?在目前的情况下,是否可以使用1.0*mt() / mt.max()
来代替?
编辑:
我用g++-11 test.cpp
编译了这段代码。当我使用-O3
标志编译时,结果在质量上是相同的(方法1大约是。速度慢1.8倍)。我想谈谈广泛使用的方法的优点.我确实关注表演的趋势,但具体的性能比较超出了我的范围。
发布于 2022-02-12 06:56:21
您使用标准随机库,因为正确地进行数值计算是非常困难的,而且您不想要证明和维护自己的随机库的负担。
例如,你的随机分布是错误的。std::mt19937
生成32位整数,但是您需要一个具有53位意义的double
(通常)。在范围[0, 1]
中有一些值您永远不会从1.0*mt() / mt::max()
中获得。
发布于 2022-02-12 06:59:11
您的测试方法存在缺陷。您不使用所生成的结果,因此聪明的优化器可能简单地跳过生成结果。
,你能告诉我使用std::uniform_real_distribution有什么意义吗?
,
使用1.0*mt() / mt.max()有什么缺点?
distribution.
使用1.0*mt() / mt.max()是否可以接受?
在某些用例中,这是可以接受的。在其他一些情况下,这是不可接受的。在其他地方,这不重要。
https://stackoverflow.com/questions/71089479
复制相似问题