2010-09-23 130 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