C++ 联合的性能影响

B_o*_*old 5 c++ cpu-registers unions

Agner Fog 的“Optimizing software in C++”中指出: union会强制将变量存储在内存中,即使变量本来可以存储在寄存器中,这可能会对性能产生影响。(例如第148页)

我经常看到这样的代码:

struct Vector {
    union {
        struct {
            float x, y, z, w;
        };
        float v[4];
    }
};
Run Code Online (Sandbox Code Playgroud)

这可能非常方便,但现在我想知道是否可能会造成潜在的性能影响。我编写了一个小型基准测试,比较带有和不带有联合的 Vector 实现,并且在某些情况下,没有联合的 Vector 显然表现更好,尽管我不知道我的基准有多值得信赖。(我比较了三种实现:union; x, y, z, w; v[4]。例如,v[4] 在按值传递时似乎更慢,尽管结构体都具有相同的大小。)

我现在的问题是,人们在编写实际生产代码时是否会考虑这一点?您是否知道专门因为这个原因而对工会做出不利于工会的案例?

Pet*_*ter 1

目标似乎是为向量类型的元素提供友好的名称,并且union并不是最好的方法。评论已经指出了未定义的行为,即使它有效,它也是一种限制优化机会的别名形式。

相反,避免整个混乱,只需添加命名元素的访问器即可。

struct quaternion
{
    float vec[4];
    float &x() { return vec[0]; }
    float &y() { return vec[1]; }
    float &z() { return vec[2]; }
    float &w() { return vec[3]; }
    const float &x() const { return vec[0]; }
    const float &y() const { return vec[1]; }
    const float &z() const { return vec[2]; }
    const float &w() const { return vec[3]; }
}
Run Code Online (Sandbox Code Playgroud)

事实上,就像 Eigen 对其四元数实现所做的那样: https://eigen.tuxfamily.org/dox/Quaternion_8h_source.html

  • 那些‘void’不应该存在。这是 C 语言中表示不带参数的函数的方式(与任意数量的参数相反)。在 C++ 中,此语法是有效的,但多余且不寻常。带有空参数列表的函数声明恰好意味着:没有参数。我还强烈建议添加 const 限定重载。因为便利访问器对于“const 四元数”是不可用的。 (2认同)