【问题标题】:Speed difference between global and object variable全局变量和对象变量之间的速度差异
【发布时间】:2010-09-23 06:24:29
【问题描述】:

访问全局变量或对象变量是否更快?

在 C++ 中,我指的是两者的区别

::foo

this->foo

在 x86 汇编器中,这基本上转换为

mov eax, offset foo

mov eax, dword ptr[edx+foo]

这两种情况下的所有数据都应该在缓存中。

(我知道差异会很小,通常应该选择使代码更简单的那个;但在这种情况下,实际上没有其他差异,所讨论的代码可能会被调用十亿次在时间限制内,所以我还是选择稍微快一点的。)

【问题讨论】:

  • 测试和计时这两个变体怎么样?
  • 如果它很重要,那么值得计时。也就是说,成员变量可能会更频繁地与您的其他数据一起缓存。
  • “有时间限制”?这是什么时限?每秒 50 亿次访问可能意味着它在性能方面很重要,但每小时 50 亿次访问则完全无关紧要。

标签: c++ assembly x86


【解决方案1】:

您需要同时测试和计时。

但是,这样做时要知道您在应用中做出的其他决定会比这对性能产生更大的影响几个数量级

在人眼看来,全局访问速度更快,但是编译器决定将什么放在哪里,以及处理器决定缓存的方式最终将决定哪个更快。

测试它并计时。如果你在一个非平凡的应用程序中获得数百万次运行的有意义的差异,我会感到震惊。

【讨论】:

  • 反对票是因为 . . .?如果你不同意我的回答,你能告诉我为什么吗?我想知道它有什么问题,毕竟我们都是来学习的:)
【解决方案2】:

请不要为了速度而优化它。

两者之间存在重要的语义差异,它为您的代码带来的价值,以及最符合逻辑意义的地方的数据,将比降低运行时性能为您节省更多时间。

数十亿次迭代实际上并没有那么多。我电脑中的 CPU 以惊人的 2.2Ghz 运行。如果它在缓存中,则取消引用可能会花费一个额外的周期,因此 1000 亿次循环大约需要 30 秒的运行时间。我怀疑我会想念它。

【讨论】:

    【解决方案3】:

    您是否考虑过第三种选择?

    void bar()
    {
       foo_t myFoo = ::foo; // or this->foo
       for(;;)
       {
           // do something with myFoo
       }
       ::foo = myFoo;
    }
    

    在这种情况下,编译器很可能会将 foo 放入寄存器中,这肯定比缓存访问还要快。

    【讨论】:

    • 编译器在分配寄存器方面并没有那么糟糕。事实上,我不知道有任何编译器尊重register 关键字,因为他们都确信他们根本不需要提示。
    • 编译器更倾向于将寄存器用于局部变量而不是必须有地址的变量,例如全局变量(存在于可执行映像中)或显式取消引用的值(例如this->foo
    【解决方案4】:

    与往常一样,选择使代码更简单的方法。

    如果您使用全局变量,那么代码的读者必须想知道为什么,以及该变量是从哪里访问的。它从多少个线程访问?不同线程的访问如何同步?

    如果您创建一个仅在需要的地方可见的局部变量,那么这些问题就迎刃而解了。

    在速度方面,唯一可能产生影响的是缓存局部性。如果变量经常被访问,它在两种情况下都会被缓存,但如果它位于其他最近使用的对象旁边,它们将能够共享相同的缓存行,从而在缓存中为其他数据留出更多空间.

    但如果代码值得优化,那么它也值得衡量。

    避免使用全局变量是一种简单、干净的选择。如果性能有问题,并且您的测量结果表明使用全局更快,则切换到全局。

    但请记住,您也在更改程序的语义。如果你有多个线程调用该函数,如果你使用一个全局的,你会得到一个竞争条件,它之前是安全的

    【讨论】:

    • +1 表示“如果代码值得优化,那么它也值得衡量”。请注意,某些(“低性能”)处理器可能会出现速度差异。更重要的是,具有小偏移量的相对负载可能会比绝对负载更小(代码方面);我通常更喜欢在 I-cache 中占用更少空间的版本。
    【解决方案5】:

    正如前面的评论员所说,衡量它。比较汇编程序指令对您没有帮助。预测计算机 cpu 缓存的行为几乎是不可能的,并且取决于其他所需的数据。此外,您的程序不一定受 CPU 限制。

    您可能希望使用 placement new 来确保持有 foo 的对象在内存中的方便位置以避免页面错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-21
      • 1970-01-01
      • 1970-01-01
      • 2022-06-16
      • 1970-01-01
      • 2017-06-09
      • 2019-12-28
      相关资源
      最近更新 更多