2011-09-10 34 views
5

說一個內核中的線程正在旋轉一個變量,該變量將由運行在另一個內核上的線程更新。我的問題是什麼是在緩存級別的開銷。請等待的線程緩存變量,並因此不會導致總線上的任何流量,直到寫入線程寫入該變量?高速緩存一致性方面的自旋循環開銷

如何減少這種開銷。 x86 pause指令有幫助嗎?

+0

我假設你指的是SMP? –

+0

是的Eli,我指的是SMP系統。 – MetallicPriest

回答

3

我相信所有現代x86 CPU都使用MESI protocol。因此,旋轉的「讀取器」線程可能會以「獨佔」或「共享」模式緩存數據副本,在旋轉時不會產生內存總線流量。

只有當另一個內核寫入該位置時,它纔會執行跨核心通信。

[更新]

A「自旋鎖」像這僅僅是一個好主意,如果你不會被旋轉很長時間。如果在變量更新之前可能需要一段時間,請改用互斥鎖+條件變量,這會讓線程進入睡眠狀態,以便在等待時不會增加開銷。

(順便說一句,我懷疑很多人 - 包括我在內 - 想知道「什麼是你真正想要做什麼?」)

+0

「我相信所有現代x86 CPU都使用MESI協議。」 - 你爲什麼相信它?我認爲AMD64是MOESI,英特爾的numa(i *)是MESIF。 – osgx

+0

@osgx:因爲我上次讀到它的時間是5 - 10年前?我不認爲它改變了基本答案,但感謝你提供的信息。 – Nemo

1

如果你短時間旋轉鎖定,你通常會很好。然而,在Linux上有一個計時器中斷(我假設其他操作系統類似),所以如果你鎖定10毫秒或接近它,你會看到緩存干擾。

我聽說有可能修改Linux內核以防止特定內核中的所有中斷,並且這種干擾消失,但我不知道這是幹什麼的。

+0

我認爲RHEL 5允許通過命令行應用程序[IRQ綁定](http://rt.et.redhat.com/wiki/index.php?title=RHEL-RT_AffinityHowto&printable=yes#IRQ_.28interrupt.29_binding)。 –

+0

確實如此,但「本地計時器中斷」無法移動,因爲它每秒至少中斷100次線程。 (它可以配置得更高)如果你知道如何關閉它,我會非常感興趣。 ;) –

0

在兩個線程的開銷的情況下,可以忽略不計了,反正它做一個簡單的基準可能是一個好主意。例如,如果您實施螺旋鎖,線程花費多少時間進入旋轉。 這個效果在緩存上叫做緩存線彈跳

0

我在this post中對此進行了廣泛的測試。一般的開銷是由自旋鎖的總線鎖定組件引起的,通常是指令「xchg reg,mem」或它的一些變體。由於無法避免特定的開銷,因此您可以選擇節省調用自旋鎖的頻率,並在釋放鎖之前執行絕對最低的工作量(一旦鎖定到位)。