簡體   English   中英

lock xchg與mfence具有相同的行為嗎?

[英]Does lock xchg have the same behavior as mfence?

我想知道的是,如果一個線程訪問一個正在被其他線程突變的內存位置(讓我們隨便說),那么lock xchg會對mfence產生類似的行為。 它能保證我獲得最新的價值嗎? 之后的內存讀/寫指令?

我混淆的原因是:

8.2.2“讀取或寫入不能通過I / O指令,鎖定指令或序列化指令重新排序。”

-Intel 64 Developers Manual Vol。 3

這是否適用於線程?

mfence說:

對MFENCE指令之前發出的所有內存加載和存儲到內存指令執行序列化操作。 此序列化操作保證在MFENCE指令之前的任何加載或存儲指令全局可見之前,在程序順序之前的每條加載和存儲指令都是全局可見的。 MFENCE指令針對所有加載和存儲指令,其他MFENCE指令,任何SFENCE和LFENCE指令以及任何序列化指令(例如CPUID指令)進行排序。

-Intel 64 Developers Manual Vol 3A

聽起來更有力。 因為聽起來mfence幾乎正在mfence寫寫緩沖區,或者至少延伸到寫緩沖區和其他內核以確保我未來的加載/存儲是最新的。

當基准標記時,兩個指令都需要約100個循環才能完成。 所以我無論如何都看不出那么大的差異。

主要是我只是困惑。 我的指令基於互斥lock使用的鎖,但是這些包含沒有內存柵欄。 然后,我看到使用內存柵欄自由編程,但沒有鎖。 我知道AMD64有一個非常強大的內存模型,但過時的值可以在緩存中持續存在。 如果lock的行為與mfence行為不同,那么互斥鎖如何幫助您查看最新值?

我相信你的問題與詢問mfence是否具有與x86上的lock前綴指令相同的屏障語義,或者它是否在某些情況下提供更少的1或額外保證相同。

我目前最好的答案是,這是英特爾的意圖 ,並且ISA文檔保證mfencelock指令提供相同的防護語義,但由於實現疏忽, mfence實際上在最近的硬件上提供了更強的防護語義(至少從Haswell開始) 。 特別是, mfence可以mfence來自WC型存儲區域的后續非臨時負載 ,而lock指令則不會。

我們知道這一點,因為英特爾在處理器勘誤中告訴我們這一點,例如HSD162(Haswell)SKL155(Skylake) ,它告訴我們鎖定的指令不會阻止從WC內存的后續非時間讀取:

來自WC內存的MOVNTDQA可能會通過更早的鎖定指令

問題:從WC(寫入組合)存儲器加載的(V)MOVNTDQA(流加載指令)的執行可能看起來通過訪問不同高速緩存行的較早鎖定指令。

含義:期望鎖定后續(V)MOVNTDQA指令的軟件可能無法正常運行。

解決方法:未確定。 依賴於鎖定指令來阻止后續執行(V)MOVNTDQA的軟件應在鎖定指令和后續(V)MOVNTDQA指令之間插入MFENCE指令。

由此,我們可以判斷:(1)英特爾可能是打算從WC型內存鎖定指令圍欄NT負載,否則這不會是一個勘誤表0.5(2)鎖定指令實際上沒有這樣做,英特爾無法或不選擇使用微代碼更新來修復此問題,建議使用mfence

在Skylake中, mfence實際上失去了相對於NT負載的附加防護能力,根據SKL079:來自WC內存的MOVNTDQA可以通過早期的MFENCE指令 - 這與lock -instruction勘誤表幾乎相同,但適用於mfence 但是,這個勘誤表的狀態是“BIOS可能包含此錯誤的解決方法。”,這通常是英特爾所說的“微代碼更新解決了這個問題”。

這個勘誤序列也許可以用時間來解釋:Haswell勘誤表只出現在2016年初,即該處理器發布后的幾年,所以我們可以假設這個問題在此之前的適當時間內引起了英特爾的注意。 在這一點上,Skylake幾乎可以肯定已經出現在野外,顯然是一個不太保守的mfence實現,也沒有在WC類型的內存區域mfence NT負載。 修復鎖定指令一直工作到Haswell的方式可能要么根本不可能或昂貴,基於它們的廣泛使用,但需要一些方法來限制NT負載。 mfence顯然已經完成了Haswell的工作,Skylake將被修復,以便mfence也在那里工作。

它並沒有真正解釋為什么SKL079( mfence one)出現在2016年1月,差不多兩年之前SKL155( locked一個)出現在2017年底,或者為什么后者在完全相同的Haswell勘誤之后出現了這么多。

人們可能會猜測英特爾將來會做些什么。 由於他們無法/願意通過Skylake更改Haswell的lock指令,代表數億(數十億?)已部署的芯片,他們永遠無法保證鎖定的指令可以阻止NT加載,因此他們可能會考慮制作這是未來記錄的架構行為。 或者他們可能會更新鎖定的指令,因此他們確實對這些讀取進行了限制,但實際上你可能不會依賴這十年或更長時間,直到具有當前非擊劍行為的籌碼幾乎沒有流通。

與Haswell類似,根據BV116BJ138 ,NT負載可能分別通過Sandy Bridge和Ivy Bridge上的早期鎖定指令。 早期的微體系結構也可能會遇到這個問題。 在Skylake之后,Broadwell和微體系結構中似乎不存在這個“錯誤”。

Peter Cordes在這個答案的最后寫了一些關於Skylake mfence變化的文章。

在我知道勘誤表之前,這個答案的剩余部分是我的原始答案,而這主要是出於歷史興趣。

老答案

我對答案的猜測是, mfence提供了額外的屏障功能:在使用弱有序指令(例如,NT存儲)的訪問之間以及可能在訪問弱有序區域 (例如,WC類型存儲器)之間。

也就是說,這只是一個明智的猜測,你會在下面找到我的調查細節。

細節

文檔

mfence的內存一致性影響與lock -prefixed指令(包括xchg與內存操作數,隱式鎖定)提供的程度並不完全清楚。

我認為可以肯定地說,僅僅針對回寫內存區域而不涉及任何非時間訪問, mfence提供與lock前綴操作相同的排序語義。

可以討論的是,當涉及到上述情況之外的場景時,mfence是否與lock前綴指令mfence不同,特別是當訪問涉及WB區域以外的區域或涉及非時間(流)操作時。

例如,您可以找到一些建議(例如此處此處 ),當涉及WC類型的操作(例如,NT存儲)時, mfence意味着強屏障語義。

例如,在這個帖子中引用麥卡爾平博士(重點補充):

圍欄指令僅需要絕對確保所有非臨時存儲在隨后的“普通”存儲之前是可見的。 最重要的情況是並行代碼,其中並行區域末端的“屏障”可能包括“普通”存儲。 如果沒有圍柵,處理器可能仍然在寫入組合緩沖區中修改了數據,但是通過屏障並允許其他處理器讀取寫入組合數據的“陳舊”副本。 此方案也可能適用於操作系統從一個核心遷移到另一個核心的單個線程(不確定此情況)。

我不記得詳細的推理(今天早上咖啡還不夠),但是你想要在非臨時商店之后使用的指令是MFENCE。 根據SWDM第3卷第8.2.5節,MFENCE是唯一一個防止后續加載和后續存儲在完成柵欄之前執行的柵欄指令。 令我感到驚訝的是,第11.3.1節沒有提到這一點,它告訴你在使用寫入組合時手動確保一致性是多么重要,但是沒有告訴你如何做到這一點!

我們來看看英特爾SDM的參考部分8.2.5:

加強或弱化記憶訂購模型

英特爾64和IA-32架構提供了多種機制來加強或削弱內存排序模型,以處理特殊編程情況。 這些機制包括:

•I / O指令,鎖定指令,LOCK前綴和序列化指令強制處理器的排序更強。

•SFENCE指令(引入Pentium III處理器中的IA-32架構)和LFENCE和MFENCE指令(Pentium 4處理器中引入)為特定類型的存儲器操作提供了存儲器排序和序列化功能。

這些機制可以使用如下:

總線上的存儲器映射設備和其他I / O設備通常對寫入其I / O緩沖區的順序很敏感。 I / O指令可用於(IN和OUT指令)對此類訪問強加寫入順序,如下所示。 在執行I / O指令之前,處理器等待程序中的所有先前指令完成,並且所有緩沖寫入都要耗盡到存儲器。 只有指令獲取和頁表行走才能通過I / O指令。 在處理器確定I / O指令已完成之前,不會開始執行后續指令。

多處理器系統中的同步機制可能依賴於強存儲器排序模型。 這里,程序可以使用諸如XCHG指令或LOCK前綴之類的鎖定指令來確保對存儲器的讀取 - 修改 - 寫入操作以原子方式執行。 鎖定操作通常像I / O操作一樣操作,因為它們等待所有先前的指令完成,並且所有緩沖的寫操作都要耗盡到存儲器(參見第8.1.2節“總線鎖定”)。

也可以使用序列化指令執行程序同步(參見第8.3節)。 這些指令通常用於關鍵過程或任務邊界,以在跳轉到新的代碼段或上下文切換之前強制完成所有先前的指令。 與I / O和鎖定指令一樣,處理器等待所有先前的指令完成,並且在執行序列化指令之前已將所有緩沖的寫入耗盡到存儲器。

SFENCE,LFENCE和MFENCE指令提供了一種性能有效的方法,可確保在生成弱排序結果的例程和使用該數據的例程之間加載和存儲內存順序 這些說明的功能如下:

•SFENCE - 序列化程序指令流中SFENCE指令之前發生的所有存儲(寫入)操作,但不影響加載操作。

•LFENCE - 序列化程序指令流中LFENCE指令之前發生的所有加載(讀取)操作,但不影響存儲操作。

•MFENCE - 序列化程序指令流中MFENCE指令之前發生的所有存儲和加載操作。

請注意,SFENCE,LFENCE和MFENCE指令提供了一種比CPUID指令更有效的控制內存排序的方法。

與麥卡爾平博士的解釋2相反,我認為這一部分對於mfence是否做了額外的事情有些含糊不清。 涉及IO,鎖定指令和序列化指令的三個部分確實意味着它們在操作之前和之后的存儲器操作之間提供了完全屏障。 它們對於弱有序的存儲器沒有任何例外,並且在IO指令的情況下,人們還假設它們需要以弱有序的存儲區域以一致的方式工作,因為這些通常用於IO。

然后是FENCE指令的部分,它明確提到弱內存區域:“SFENCE,LFENCE和MFENCE指令**提供了一種性能有效的方法來確保在生成弱有序結果和例程的例程之間加載和存儲內存排序消耗這些數據。“

我們是否在這些行之間進行了閱讀,並認為這些是完成此操作的唯一指令,並且前面提到的技術(包括鎖定指令)對弱內存區域沒有幫助? 我們可以通過注意圍欄指令與弱序非時態存儲指令同時引入3以及11.6.13 Cacheability Hint指令中專門針對弱有序指令處理的文本來找到對此思想的一些支持:

數據消費者知道數據被弱排序的程度可能因這些情況而異。 因此,應使用SFENCE或MFENCE指令來確保生成弱排序數據的例程和使用數據的例程之間的排序。 SFENCE和MFENCE通過保證程序順序中SFENCE / MFENCE之前的每個商店指令在跟​​隨圍欄的商店指令之前是全局可見的,提供了一種性能有效的方式來確保訂購。

同樣,這里特別提到圍柵指令適用於屏蔽弱有序指令。

我們還發現支持這樣一種觀點,即鎖定指令可能不會在上面已經引用的最后一個句子的弱有序訪問之間提供障礙:

請注意,SFENCE,LFENCE和MFENCE指令提供了一種比CPUID指令更有效的控制內存排序的方法。

這基本上意味着FENCE指令實質上取代了先前由序列化cpuid在內存排序方面提供的功能。 但是,如果lock -prefixed指令提供了與cpuid相同的屏障功能,那么這可能是之前建議的方式,因為這些通常比cpuid快得多,后者通常需要200個或更多周期。 這意味着存在lock前綴指令無法處理的場景(可能是弱序場景),以及使用cpuid地方,以及現在建議將mfence作為替換,暗示比lock前綴指令更強的屏障語義。

但是,我們可以用不同的方式解釋上面的一些內容:請注意,在圍欄指令的上下文中,經常提到它們是確保排序的性能有效方式 因此,這些說明可能並非旨在提供額外的障礙,而只是提供更有效的障礙。

實際上,幾個周期的sfence比串行化指令要快得多,例如cpuidlock前綴指令,通常是20個周期或更多。 在另一方面mfence 不是一般至少比在現代硬件鎖定指令4,速度更快。 盡管如此,它在引入或未來某些設計時可能會更快,或者預計它會更快但但並沒有成功。

所以我不能根據手冊的這些部分做出一定的評估:我認為你可以做出合理的論證,可以用任何一種方式解釋它。

我們可以進一步查看英特爾ISA指南中各種非臨時存儲指令的文檔。 例如,在非臨時存儲movnti的文檔中,您會找到以下引用:

由於WC協議使用弱排序的內存一致性模型,如果多個處理器可能使用不同的內存類型來讀/寫目標內存位置,則應使用SFENCE或MFENCE指令實現的防護操作與MOVNTI指令一起使用。

關於“如果多個處理器可能使用不同的存儲器類型來讀/寫目標存儲器位置”的部分對我來說有點混亂。 我希望這可以說“在使用弱排序提示的指令之間強制執行排序”或類似的東西。 實際上,實際的存儲器類型 (例如,由MTTR定義)可能在這里甚至不起作用:當使用弱有序指令時,排序問題可能僅在WB存儲器中出現。

性能

據報道, mfence指令在現代CPU上基於Agner fog的指令時序需要33個周期(背靠背延遲),但據報道, lock cmpxchg等更復雜的鎖定指令只需要18個周期。

如果mfence提供的屏障語義不比lock cmpxchg強,后者正在嚴格執行更多的工作,並且沒有明顯的理由讓mfence花費更長的時間 當然你可以爭辯說, lock cmpxchgmfence更重要,因此可以獲得更多優化。 由於所有鎖定的指令都比mfence ,即使不經常使用的指令,這個論點也會被削弱。 此外,您可以想象如果所有lock指令共享一個屏障實現,則mfence將使用相同的那個,因為它是最簡單且最容易驗證的。

因此,在我看來, mfence的較慢表現是證據表明mfence正在做一些額外的事情。


0.5這不是一個不透水的論點。 有些東西可能出現在勘誤表中,顯然是“按設計”而不是錯誤,例如popcnt錯誤依賴於目標寄存器 - 因此一些勘誤表可以被視為一種更新期望的文檔形式,而不是總是暗示硬件錯誤。

1顯然, lock -prefixed指令執行原子操作,這是不可能僅使用mfence實現的,因此lock前綴的指令肯定具有附加功能。 因此,為了使mfence有用,我們希望它在某些場景中具有額外的屏障語義, 或者表現更好。

2他完全有可能閱讀散文不同的手冊的不同版本。

3 SFENCE在SSE, lfencemfence在SSE2。

4通常它的速度較慢:Agner在最近的硬件上列出了33個周期的延遲,而鎖定指令通常約為20個周期。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM