gpt4 book ai didi

c++ - 在类中使用随机生成器时的性能问题

转载 作者:行者123 更新时间:2023-12-02 03:30:04 24 4
gpt4 key购买 nike

我的目标是使用 Mersenne Twister 创建一个围绕 Boost 均匀实数分布的包装器,以便使其在库中可用。所以我创建了一个像这样的基本类:

class mt19937
{
protected:
boost::random::mt19937 gen_;
boost::random::uniform_real_distribution<double> real_;
public:
mt19937(unsigned long s = 5489UL) : gen_(s), real_(0., 1.) {};
double get() { return real_(gen_); };
};

尽管运行性能测试,我发现我的类比直接调用 Boost 对象慢得多。事实上,下面的代码对 100 亿个数字进行采样,在我的机器上需要 30 秒:

constexpr unsigned long seed = 5489UL;
constexpr size_t iter = 100000;
double x = 0.;

boost::random::mt19937 gen(seed);
boost::random::uniform_real_distribution<double> real(0., 1.);

for (size_t i = 0; i < iter; ++i)
for (size_t j = 0; j < iter; ++j)
x = real(gen);

上面描述的类mt19937,使用以下代码,大约需要70秒:

mt19937 stduniform(seed);

for (size_t i = 0; i < iter; ++i)
for (size_t j = 0; j < iter; ++j)
x = stduniform.get();

查看 Windows 中的汇编程序,在第一种情况下,为 x = real(gen) 执行的代码如下,在我看来,这只是对 boost::random 的调用: :detail::generate_uniform_real 以及对 x 的赋值:

00007FF6D14639F0  movzx       r9d,byte ptr [r15]  
00007FF6D14639F4 lea rcx,[gen]
00007FF6D14639F9 movaps xmm2,xmm7
00007FF6D14639FC movaps xmm1,xmm8
00007FF6D1463A00 call boost::random::detail::generate_uniform_real<boost::random::mersenne_twister_engine<unsigned int,32,624,397,31,2567483615,11,4294967295,7,2636928640,15,4022730752,18,1812433253>,double> (07FF6D146141Ah)

使用函数get(),我看到以下指令 - 它似乎对寄存器执行了一些我无法解释的操作和跳转:

00007FF6D1463B61  movsd       xmm3,mmword ptr [rbp+900h]  
00007FF6D1463B69 lea rcx,[stduniform]
00007FF6D1463B6E movsd xmm4,mmword ptr [rbp+8F8h]
00007FF6D1463B76 movaps xmm2,xmm3
00007FF6D1463B79 mulsd xmm2,xmm6
00007FF6D1463B7D movaps xmm1,xmm4
00007FF6D1463B80 mulsd xmm1,xmm6
00007FF6D1463B84 movaps xmm0,xmm2
00007FF6D1463B87 subsd xmm0,xmm1
00007FF6D1463B8B comisd xmm0,xmm7
00007FF6D1463B8F jbe main+2F8h (07FF6D1463B98h)
00007FF6D1463B91 call boost::random::detail::generate_uniform_real<boost::random::mersenne_twister_engine<unsigned int,32,624,397,31,2567483615,11,4294967295,7,2636928640,15,4022730752,18,1812433253>,double> (07FF6D14615D7h)
00007FF6D1463B96 jmp main+307h (07FF6D1463BA7h)
00007FF6D1463B98 movzx r9d,byte ptr [rbx]
00007FF6D1463B9C movaps xmm2,xmm3
00007FF6D1463B9F movaps xmm1,xmm4
00007FF6D1463BA2 call boost::random::detail::generate_uniform_real<boost::random::mersenne_twister_engine<unsigned int,32,624,397,31,2567483615,11,4294967295,7,2636928640,15,4022730752,18,1812433253>,double> (07FF6D146141Ah)

对函数(应内联)的调用执行 100 亿次是否可能会增加此开销?您对 boost 性能的代码有什么建议吗?

我在Windows环境下工作,使用VisualStudio2015的vc14编译器,Boost 1.7.1。我在 Linux 机器上的 gcc4.9 中观察到类似的行为,其中直接调用 Boost 需要 30 秒,而新类需要 45 秒。

非常感谢您的宝贵时间。

最佳答案

您强调的“我无法解释的一些寄存器操作”:

00007FF6D1463B61  movsd       xmm3,mmword ptr [rbp+900h]  
00007FF6D1463B69 lea rcx,[stduniform]
00007FF6D1463B6E movsd xmm4,mmword ptr [rbp+8F8h]
00007FF6D1463B76 movaps xmm2,xmm3
00007FF6D1463B79 mulsd xmm2,xmm6
00007FF6D1463B7D movaps xmm1,xmm4
00007FF6D1463B80 mulsd xmm1,xmm6
00007FF6D1463B84 movaps xmm0,xmm2
00007FF6D1463B87 subsd xmm0,xmm1
00007FF6D1463B8B comisd xmm0,xmm7
00007FF6D1463B8F jbe main+2F8h (07FF6D1463B98h)

似乎与generate_uniform_real中的以下几行匹配:

T result = numerator / divisor * (max_value - min_value) + min_value;
if(result < max_value) return result;

因此编译器似乎无法将 min_valuemax_value 参数内联到此函数。

无论如何,我无法在以下方面重现显着的性能差异:

  • Apple clang 版本 11.0.0 (clang-1100.0.33.17)
  • boost 1.69.0_2

关于c++ - 在类中使用随机生成器时的性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60298568/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com