【问题标题】:Are there any performance penalties when using nested structures?使用嵌套结构时是否有任何性能损失?
【发布时间】:2010-09-16 23:25:26
【问题描述】:

当我使用多个嵌套结构/类(有点像使用多维堆数组)时是否有任何性能损失,或者它只是语言的一种组织特性,可以更容易地跟踪数据而编译器没有真的看出什么不同了吗?

谢谢

【问题讨论】:

    标签: c++ performance data-structures


    【解决方案1】:

    不是真的。类/结构只是在内存中定义偏移量,所以如果你在类中的类中有一个类,编译器只是将偏移量相加。

    一旦有了指针(每个指针取消引用都是内存读取和潜在的 L2 缓存未命中)或虚拟函数(非常糟糕,尤其是在较旧的 CPU 上),性能就会发挥作用。

    编辑:我应该注意的一件事 - 如果您正在开发一个性能不是绝对重要的应用程序,请关注良好的类设计而不是性能。虽然当您编写需要以 60fps 运行的内容时,L2 缓存未命中之类的事情会产生很大的影响,但在普通桌面应用程序中却没有什么意义。

    【讨论】:

    • 所以指针会受到惩罚?
    • 尊重他们。 pA->pB->pC->pD 将强制系统从四个地址读取。每一个都可能位于不同的缓存页面中,并导致代价高昂的 L2 缓存未命中。由于您必须遵循 pA 来找出 pB,因此您将无法预取。但是:指针对于使很少使用的数据远离主结构很有用,因此,如果您有一个需要大量迭代的结构数组,请保留您在结构中使用的实际数据和所有很少使用的东西在单独的类/结构中,以便您需要获取更少的缓存页面。
    • 虚函数调用只是为了从vtable中获取函数地址而进行的一两次内存解引用,然后是一次函数调用。性能并不比 C 中带有函数指针的结构差很多。以及诸如此类的结构在 linux 内核中无处不在
    • 在较旧的 CPU 上也无法预测虚拟函数调用(以及函数指针调用),这是除了潜在的 L2 缓存未命中之外的另一个性能损失。一般来说 - 如果你不需要虚拟的东西(或回调),那么不要那样做。但是,请记住我对答案所做的编辑。不要仅仅为了无法衡量的性能提升而编写糟糕的代码。
    【解决方案2】:

    不应该有任何性能或内存损失。它们只是让程序员更轻松的语法糖。

    【讨论】:

      【解决方案3】:

      简短回答:不。

      【讨论】:

        【解决方案4】:

        大多数情况下没有,正如其他人所提到的。但是,有一个小例外:相对于将相同的原语直接放入单个结构中,由于对齐问题,将结构放入结构中可能会导致较小的内存使用损失。从理论上讲,这可能会导致缓存未命中,从而损害性能。例如:

        #include <iostream>
        using namespace std;  // So sue me
        
        struct A {
            double d;
            int i;
        };
        
        struct B {
            int j;
            int k;
            int l;
        };
        
        struct AB {
            A a;
            B b;
        };
        
        struct C {
            double d;
            int i;
            int j;
            int k;
            int l;
        };
        
        int main() {
            cout << sizeof(AB) << endl;  // 32
            cout << sizeof(C) << endl;   // 24
        }
        

        【讨论】:

        • 编译器优化会处理这个问题吗?它看起来几乎像一个内联类型优化。
        • 编译器优化无法解决这个问题,因为结构的布局是 ABI 的一部分,需要明确指定。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-27
        • 1970-01-01
        • 2011-04-06
        • 1970-01-01
        • 2018-04-23
        • 2016-11-10
        • 1970-01-01
        相关资源
        最近更新 更多