使用空构造函数会使数组未初始化,从而导致计算速度变慢

dar*_*uki 6 c++ optimization default-constructor compiler-optimization visual-studio-2013

我对一件事感到非常困惑...如果我将构造函数添加到 struct A 中,那么 for 循环中的计算会变得慢很多倍。为什么?我不知道。

在我的计算机上,输出中的代码片段的时间为:

有构造函数:1351

没有构造函数:220

这是一个代码:

#include <iostream>
#include <chrono>
#include <cmath>

using namespace std;
using namespace std::chrono;

const int SIZE = 1024 * 1024 * 32;

using type = int;

struct A {
    type a1[SIZE];
    type a2[SIZE];
    type a3[SIZE];
    type a4[SIZE];
    type a5[SIZE];
    type a6[SIZE];

    A() {} // comment this line and iteration will be twice faster
};

int main() {
    A* a = new A();
    int r;
    high_resolution_clock::time_point t1 = high_resolution_clock::now();
    for (int i = 0; i < SIZE; i++) {
        r = sin(a->a1[i] * a->a2[i] * a->a3[i] * a->a4[i] * a->a5[i] * a->a6[i]);
    }
    high_resolution_clock::time_point t2 = high_resolution_clock::now();

    cout << duration_cast<milliseconds>(t2 - t1).count() << ": " << r << endl;

    delete a;

    system("pause");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我从 for 循环中删除 sin() 方法,如下所示:

for (int i = 0; i < SIZE; i++) {
    r = a->a1[i] * a->a2[i] * a->a3[i] * a->a4[i] * a->a5[i] * a->a6[i];
}
Run Code Online (Sandbox Code Playgroud)

删除构造函数并不重要,执行时间是相同的,等于 78。

您对这段代码有类似的行为吗?你知道其中的原因吗?

编辑:我用 Visual Studio 2013 编译它

Fed*_*dor 2

是的,如果在发布配置中进行编译(经过优化),此行为在 Visual Studio 2019 中仍然可以重现。

如果struct A有空的用户构造函数,则其字段在 后保持未初始化状态new A()

另一方面,如果struct A没有构造函数,那么它会成为聚合new A()用零填充其字段。

计算乘法和正弦具有相同的性能,与输入参数无关(如果它们不是非标准化值,这里不是这种情况),但在初始化带有零的字段后,它们出现在 CPU 缓存中,因此以下计算速度更快,这解释了无构造函数版本的“好处”(当然,如果不包括在测量中对象构造的时间)。

如果保留空构造函数,然后手动用零填充对象:

    A* a = new A();
    for (int i = 0; i < SIZE; i++)
        a->a1[i] = a->a2[i] = a->a3[i] = a->a4[i] = a->a5[i] = a->a6[i] = 0;
Run Code Online (Sandbox Code Playgroud)

那么程序将与 中没有构造函数的情况一样快A