2011-11-02 36 views
7

解引用指針是否比直接訪問該值要慢?我想我的問題是 - 尊敬操作符有多快?指針間接影響效率多少?

+3

難道你關心的是速度還是記憶? – ruslik

+0

你的速度或記憶問題? –

+1

不可能一般回答。訪問L1緩存的內存訪問將比訪問實際內存的訪問速度快數百倍(可能是數千倍)。不要推測;基準。 – Nemo

回答

20

通過指針間接尋址由於現代CPU的工作原理,會慢得多。但它與運行時內存沒有太大關係。

相反,速度受預測和緩存的影響。

當指針未被更改或以可預測的方式更改時(例如,循環中增加或減少四),預測很容易。這允許CPU在實際代碼執行之前基本上運行,找出指針值將會是什麼,並將該地址加載到緩存中。當指針值由像哈希函數這樣的複雜表達式構建時,預測變得不可能。

緩存起作用,因爲指針可能指向不在緩存中的內存,它將不得不被提取。如果預測有效,這將被最小化,但如果預測不可能,那麼在最壞的情況下,您可能會產生雙重影響:指針不在緩存中,指針目標也不在緩存中。在最壞的情況下,CPU會停頓兩次。

如果指針用於函數指針,則CPU的分支預測器開始工作。在C++虛擬表中,函數值都是恆定的,預測器很容易。當執行通過間接跳轉時,CPU將準備好運行代碼並在流水線中。但是,如果它是一個不可預知的函數指針,性能影響可能會很大,因爲流水線需要刷新,每次跳轉會浪費20-40個CPU週期。

+0

好吧,如果我有一對使用緩衝區的嵌套循環(每次它使用緩衝區,它在這個fnc中將指針取消引用兩次),指針值將會(presumabley)是可預測的?它不會真的重要嗎? – user965369

+2

如果緩衝區足夠小以適應緩存,則無論它們是否可預測,內存訪問都將非常快。 – Nemo

+0

@ user965369:盡你所能確保緩衝區適合L1緩存,如果你不能這樣做,至少可以將它適合L2緩存。爲了最大速度處理緩存大小塊中較大的緩衝區。 –

2

它需要存儲器訪問更多:

  1. 讀存儲到指針變量
  2. 讀取該地址處的值讀取

這可能不等於2操作簡單的地址,因爲訪問尚未加載到緩存中的地址也可能需要更多時間。

+0

它需要*內存訪問*更多,這可能是在一個緊密的循環禁止。並非所有的CPU操作都是相同的。 –

+0

是的..你是對的..我解決了我的回答 – Heisenbug

2

它的確如此。它需要額外的提取。
通過值訪問變量,變量直接從其內存位置讀取。
通過指針訪問相同的內容會增加從指針中獲取變量地址的開銷,然後從該內存位置讀取值。

Ofcourse,假設變量沒有放在寄存器中,它會在一些情況下,如緊密循環。我相信這個問題會在假設沒有這種情況下尋求間接成本的回答。

3

要看的東西,如:

  • 的「直接訪問」值是否在寄存器中已經,或在棧上(這也是一個間接指針)
  • 目標地址是否在緩存中已經
  • 的高速緩存架構,總線架構等

即太多的變量,有效地推測不縮小下來。

如果您真的想知道,請在您的特定硬件上進行基準測試。

2

假設你正在處理一個真正的指針(不是某種智能指針),取消引用操作根本不消耗(數據)內存。它確實(可能)涉及額外的內存引用:一個用於加載指針本身,另一個用於訪問指針指向的數據。

但是,如果您在緊密循環中使用指針,它通常會在持續時間內加載到寄存器中。在這種情況下,成本主要是在額外註冊壓力方面(即,如果您使用寄存器來存儲該指針,則不能用它來同時存儲其他內容)。如果你有一個算法,否則正好填充寄存器,但註銷指針會溢出到內存它可以有所作爲。曾經,這是一個非常大的損失,但是對於大多數現代CPU(具有更多寄存器和板載高速緩存),這很少成爲一個大問題。明顯的例外是嵌入式CPU,寄存器較少,沒有緩存(並且沒有片上存儲器)。

底線是它通常很小,通常低於閾值,甚至可以可靠地進行測量。