2010-09-23 118 views
0

访问全局变量或对象变量是否更快?全局变量和对象变量之间的速度差异

在C++中,我

::foo 

this->foo 

之间参照差在x86汇编,这基本上转化为

mov eax, offset foo 

VS

mov eax, dword ptr[edx+foo] 

这两种情况下的所有数据都预计在缓存中。 (我知道区别是什么会很小,而且通常应该选择哪个代码更简单;但在这种情况下,实际上没有其他区别,并且有问题的代码将被称为大概5亿个时间限制在一段时间内,所以我还不如去更快的那个)

+2

怎么样测试和计时两个变种? – sharptooth 2010-09-23 06:26:34

+1

如果重要,这是值得的时间。也就是说,成员变量可能会更频繁地与其他数据缓存在一起。 – GManNickG 2010-09-23 06:29:30

+0

“限时”?这是什么时间限制?每秒五亿次访问可能意味着性能方面的重要性,但每小时五亿次将使其完全无关紧要。 – jalf 2010-09-23 08:50:29

回答

8

你需要测试和时间两个。

然而,这不知道你做了你的应用程序的其他决定,将有数量级几个数量级比这更大的性能影响

对于人类来说,Global的访问速度更快,然而编译器决定放置在哪里以及处理器如何决定缓存事物最终将决定哪个更快。

测试它和时间。如果你在一个非微不足道的应用程序中获得了数百万次运行的有意义的差异,我会惊呆了。

+0

而downvote是因为。 。 。?如果您不同意我的回答,请告诉我为什么?我想知道它有什么问题,毕竟我们都在这里学习:) – 2012-05-24 08:48:22

1

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

您可能希望使用放置新的以确保持有foo的对象在更方便的位置以避免页面错误。

4

请不要优化速度。

这两者之间存在重要的语义差异,它使您的代码与最符合逻辑意义的地方的数据相比,可以为您节省更多时间而不是减少运行时间性能。

数十亿次的迭代并不是那么多。我电脑中的CPU运行速度惊人2.2Ghz。如果它在高速缓存中,解引用将花费额外的周期,因此1000亿次循环大约需要30秒的运行时间。我怀疑我会错过它。

3

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

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

在这种情况下,编译器可能把FOO在寄存器中,这肯定是速度甚至比高速缓存访​​问。

+3

编译器在分配寄存器方面并没有那么糟糕。事实上,我不知道任何尊重“register”关键字的编译器,因为他们都确信它们根本不需要提示。 – MSalters 2010-09-23 07:44:35

+1

编译器更倾向于使用寄存器作为局部变量,而不是必须具有地址的变量,例如全局变量(存在于可执行映像中)或显式取消引用的值(如this-> foo) – SingleNegationElimination 2010-09-23 18:35:47

3

一如既往,请遵循使代码更简单的原则。

如果你使用全局的,那么代码的读者不得不怀疑为什么,以及这个变量从哪里访问。它从多少个线程访问?来自不同线程的访问如何同步?

如果你创建一个只在需要的地方可见的局部变量,那么这些问题就会消失。

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

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

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

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

+0

+1 “如果代码值得优化,那么它也值得衡量”。请注意,某些(“低性能”)处理器可能会看到速度差异。更重要的是,具有小偏移量的相对负载可能比绝对负载更小(代码方式);我通常更喜欢在I-cache中占用较少空间的版本。 – 2010-09-24 17:55:22