为什么这个自动矢量化器关心构造函数/析构函数

Why Does This Auto-Vectorizer Care About Constructors/Destructors?

本文关键字:关心 构造函数 析构函数 矢量化 为什么      更新时间:2023-10-16

这是一个SSCCE:

class Vec final {
    public:
        float data[4];
        inline Vec(void) {}
        inline ~Vec(void) {}
};
Vec operator*(float const& scalar, Vec const& vec) {
    Vec result;
    #if 1
        for (int k=0;k<4;++k) result.data[k]=scalar*vec.data[k];
    #else
        float const*__restrict src =    vec.data;
        float      *__restrict dst = result.data;
        for (int k=0;k<4;++k) dst[k]=scalar*src[k];
    #endif
    return result;
}
int main(int /*argc*/, char* /*argv*/[]) {
    Vec vec;
    Vec scaledf = 2.0f * vec;
    return 0;
}

编译时,MSVC 2013通知我(/Qvec-report:2)

main.cpp(11): info C5002:循环未矢量化,原因为'1200'

这意味着"[l]oop包含循环携带的数据依赖"。

我注意到注释Vec的构造函数或析构函数(edit:或默认它们,例如Vec()=default;)会使其成功向量化。我的问题是:为什么?


注意:切换#if也会使它工作。__restrict很重要。
注意:将float const& scalar更改为float const scalar会导致向量化报告1303(向量化不会成功),我怀疑是因为引用可以直接传递到SSE寄存器中,而值传递需要另一个副本。

为什么声明一个空的非虚析构函数inline ~Vec(void) {}和一个空的默认构造函数inline Vec(void) {} ?

因此,编译器不会生成默认的复制构造函数。因此,代码return result;没有它就无法编译,因为这需要将结果复制到一个临时返回的对象中(这可能不是您想要的)。

要么定义复制构造函数,要么根本不定义空的构造函数和析构函数