C++:结构访问速度比基本变量慢?

Roo*_*kie 14 c++ struct

我找到了一些像这样"优化"的代码:

void somefunc(SomeStruct param){
    float x = param.x; // param.x and x are both floats. supposedly this makes it faster access
    float y = param.y;
    float z = param.z;
}
Run Code Online (Sandbox Code Playgroud)

并且评论说它会使变量访问速度更快,但我一直认为结构元素访问速度和它毕竟不是结构一样快.

有人能清除我的头脑吗?

Cat*_*lus 14

经验法则:它并不慢,除非探查者说它是.让编译器担心微观优化(他们对他们非常聪明;毕竟,他们已经做了多年)并专注于更大的图景.

  • @Rookie:关于微观优化存在很多困惑.通常,避免过早优化,使用正确的数据结构和算法,然后在遇到性能瓶颈时根据测量进行优化. (4认同)

小智 12

通常的优化规则(Michael A. Jackson)适用:1.不要这样做.2.(仅限专家:)不要这样做.

话虽如此,让我们假设它是最内层的循环,占用了性能关键型应用程序的80%的时间.即便如此,我怀疑你会看到任何不同.让我们使用这段代码:

struct Xyz {
    float x, y, z;
};

float f(Xyz param){
    return param.x + param.y + param.z;
}

float g(Xyz param){
    float x = param.x;
    float y = param.y;
    float z = param.z;
    return x + y + z;
}
Run Code Online (Sandbox Code Playgroud)

通过LLVM运行它显示:只有没有优化,两者按预期运行(g将结构成员复制到本地,然后对这些进行求和; f对从param直接获取的值求和).使用标准优化级别,两者都会产生相同的代码(提取值一次,然后对它们求和).

对于简短的代码,这种"优化"实际上是有害的,因为它不必要地复制浮动.对于在几个地方使用成员的较长代码,如果你主动告诉你的编译器是愚蠢的,那么它可能会有点帮助.使用65(而不是2)添加成员/本地的快速测试证实了这一点:没有优化,f重复加载结构成员,同时g重用已经提取的本地成员.优化版本再次相同,并且仅提取成员一次.(令人惊讶的是,即使启用LTO,也没有强度降低将增加转换为乘法,但这只表明所使用的LLVM版本无论如何都没有过于激烈地优化 - 所以它应该在其他编译器中也能正常工作.)

所以,最重要的是:除非你知道你的代码必须由编译器编译,这些编译器非常愚蠢和/或古老,以至于它不会优化任何东西,你现在已经证明了编译器会使两种方式等效并且可以因此,以表演的名义废除了这种可读性和酿造性犯罪.(如有必要,请为您的特定编译器重复实验.)

  • "没有优化" - 我强调,担心没有优化编译的代码的性能是不合法的,除非你想要针对一些特定的吱吱作响的旧的非优化编译器.任何人都可以编写一个糟糕的C编译器(C++更难实际编写,但原理相同).没有必要扭曲你的代码来处理那些特定方式不好的编译器,除非这种方式是(a)相当普遍,或者由于特定原因合理地打击你; 及(b)会明显损害表现.我同意你的意见,这不是风险. (2认同)