c++ - 在循环中使用normal_distribution

标签 c++

我想知道将 normal_distribution 放入循环中是否存在问题。

这是以这种奇怪的方式使用 normal_distribution 的代码:

std::default_random_engine generator;
//std::normal_distribution<double> distribution(5.0,2.0);

for (int i=0; i<nrolls; ++i) {
    std::normal_distribution<double> distribution(5.0,2.0);
    float x = distribution(generator);

}

最佳答案

normal_distribution 对象放在循环之外可能比将其放在循环中稍微更有效。当它位于循环内部时,normal_distribution 对象可能每次都会重新构造,而如果它位于循环外部,则仅构造一次。

组件比较。

根据对程序集的分析,在循环外部声明分发效率更高。

让我们看看两个不同的函数以及相应的程序集。其中一个在循环内声明distribution,另一个在循环外声明它。为了简化分析,在这两种情况下它们都被声明为 const,因此我们(和编译器)知道分布不会被修改。

您可以看到the complete assembly here.

// This function is here to prevent the compiler from optimizing out the
// loop entirely
void doSomething(std::normal_distribution<double> const& d) noexcept;

void inside_loop(double mean, double sd, int n) {
    for(int i = 0; i < n; i++) {
        const std::normal_distribution<double> d(mean, sd); 
        doSomething(d); 
    }
}
void outside_loop(double mean, double sd, int n) {
    const std::normal_distribution<double> d(mean, sd);
    for(int i = 0; i < n; i++) {
        doSomething(d); 
    }
}

inside_loop 程序集

循环的程序集如下所示(在 O3 优化时使用 gcc 8.3 编译)。

.L3:
        movapd  xmm2, XMMWORD PTR [rsp]
        lea     rdi, [rsp+16]
        add     ebx, 1
        mov     BYTE PTR [rsp+40], 0
        movaps  XMMWORD PTR [rsp+16], xmm2
        call    foo(std::normal_distribution<double> const&)
        cmp     ebp, ebx
        jne     .L3

基本上,它 - 构建分布 - 使用发行版调用 foo - 测试是否应该退出循环

outside_loop 程序集

使用相同的编译选项,outside_loop 只需重复调用 foo 而无需重新构建发行版。指令更少,并且所有内容都保留在寄存器中(因此无需访问堆栈)。

.L12:
        mov     rdi, rsp
        add     ebx, 1
        call    foo(std::normal_distribution<double> const&)
        cmp     ebp, ebx
        jne     .L12

是否有任何理由在循环内声明变量?

是的。确实有在循环内声明变量的好时机。如果您在循环内以某种方式修改分布,那么每次通过再次构造它来重置它是有意义的。

此外,如果您从未在循环外部使用变量,则出于可读性的目的在循环内部声明它是有意义的。

适合 CPU 寄存器的类型(浮点型、整数型、 double 型和小型用户定义类型)通常没有与其构造相关的开销,并且在循环内声明它们实际上可以带来更好的汇编/em> 通过简化编译器对寄存器分配的分析。

关于c++ - 在循环中使用normal_distribution,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55857740/

相关文章:

c++ - 输入一个值后跳过一些代码并退出程序

c++ - sclite (SCTK) 安装,文件无法识别,文件格式无法识别,Cygwin

c++ - 如何正确使用 struct/std::pair?

c++ - c++中的编译错误是什么?

c++ - 虚函数效率与 'final'关键字

c++ - Rummikub 算法

c++ - C++ 中意外的 long long 值

c++ - 我可以在一个线程中写入变量并在 C++ 中的另一个线程中读取它吗

c++ - CRC32 C 或 C++ 实现

c++ - 将数字乘以矩阵