一種。使用互斥鎖訪問記憶體位置是否意味著關鍵代碼對互斥變數所做的任何事情都將最終進入主記憶體,而不僅僅是在執行緒的快取或暫存器中更新,而沒有主記憶體中值的新副本?
灣 如果是這種情況,我們是不是像沒有快取一樣有效地運行關鍵核心(至少沒有用于互斥鎖變數的快取位置)?
C。如果是這種情況,那么關鍵代碼不是重量級代碼,需要盡可能小,考慮到至少在互斥鎖的開頭和結尾繼續需要從主記憶體中讀取和寫入-鎖定會話?
uj5u.com熱心網友回復:
一種。使用互斥鎖訪問記憶體位置是否意味著關鍵代碼對互斥變數所做的任何事情都將最終進入主記憶體,而不僅僅是在執行緒的快取或暫存器中更新,而沒有主記憶體中值的新副本?
正確實作的互斥鎖可確保在釋放互斥鎖時之前的寫入對其他代理(例如其他 CPU)可見。在具有快取一致性(例如 80x86)的系統上,修改在快取中時是可見的,并且修改是否已到達主記憶體并不重要。
本質上(過度簡化),為了快取一致性,當另一個 CPU 想要修改后的資料時,它會廣播一個請求(例如“嘿,我想要地址 123456 處的資料”),如果它在另一個 CPU 的快取中,另一個 CPU 會回應使用“這是您想要的資料”,如果資料不在任何快取中,則記憶體控制器回應“這是您想要的資料”;并且 CPU 獲取最新版本的資料,無論資料在哪里或回應請求的內容如何。實際上,它要復雜得多 - 如果您有興趣(https://en.wikipedia.org/wiki/MESI_protocol),我建議您閱讀有關 MESI 快取控制協議的資訊。
灣 如果是這種情況,我們是不是像沒有快取一樣有效地運行關鍵核心(至少沒有用于互斥鎖變數的快取位置)?
如果是這種情況(例如,如果沒有快取一致性);某些東西(釋放互斥鎖的代碼)必須確保在互斥鎖可以被其他東西獲取之前將修改后的資料寫回 RAM。這不會阻止快取在臨界區內部使用(例如臨界區可以寫入快取,然后修改后的資料可以從快取發送到 RAM)。
成本將取決于各種因素(CPU 速度、快取速度和記憶體速度,以及快取是“回寫”還是“直寫”,以及修改了多少資料)。對于某些情況(具有直寫快取的相對較慢的 CPU),成本可能幾乎為零。
C。如果是這種情況,那么關鍵代碼不是重量級代碼,需要盡可能小,考慮到至少在互斥鎖的開頭和結尾繼續需要從主記憶體中讀取和寫入-鎖定會話?
它不像不使用快取那么重。
同步訪問(不管它是如何完成的)總是比不同步訪問更昂貴(并且因為所有的資料都被搞砸了而崩潰)。;-)
多執行緒代碼的挑戰之一是在同步和并行的成本之間找到一個很好的折衷——少量的鎖(或單個全域鎖)降低了同步的成本,但限制了并行(執行緒什么也不做,等待獲取一把鎖);大量的鎖增加了同步的成本(例如,獲取更多的鎖比獲取一個更昂貴)但允許更多的并行性。
當然,并行性也受您擁有的 CPU 數量的限制;這意味著對一個系統(CPU 很少)的良好折衷可能不適用于另一個系統(CPU 很多)。
uj5u.com熱心網友回復:
一種。使用互斥鎖訪問記憶體位置是否意味著關鍵代碼對互斥變數所做的任何事情都將最終進入主記憶體,而不僅僅是在執行緒的快取或暫存器中更新,而沒有主記憶體中值的新副本?
存盤在臨界區中的變數不能保證位于主存盤器(例如 RAM)中。它們可以位于 CPU 快取中(并且很可能存在)。如果變數是本地變數,或者更一般地說,如果確保它對其他執行緒不可見(即不共享),它們也可以存盤在暫存器中。但是,如果它們與其他執行緒共享,則它們不能存盤在暫存器中。在這種情況下,鎖充當記憶體屏障。這足以讓其他執行緒看到更新的內容(感謝快取一致性)。請注意,并非所有處理器實際上都需要有關其記憶體一致性模型的(慢速)記憶體屏障指令(例如,與 ARM 或 PowerPC 處理器相反,x86/x86-64 不需要該指令)。
如果您希望將變數存盤在記憶體層次結構中,您可能需要使用volatile變數。這樣的變數不會存盤在暫存器中,但可能仍然不會存盤在主存盤器中。您通常不需要它,除非您想從除錯器讀取變數,或者您想與使用硬體映射記憶體的低級設備進行互動。
C。如果是這種情況,那么關鍵代碼不是重量級代碼,需要盡可能小,考慮到至少在互斥鎖的開頭和結尾繼續需要從主記憶體中讀取和寫入-鎖定會話?
好吧,無論如何,關鍵部分需要盡可能短,以便應用程式可以適當地擴展(由于阿姆達爾定律)。最后一個屏障可能很昂貴,但如果沒有快取未命中,記憶體加載/存盤通常不會那么多,因為它們通常可以并行完成。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/362521.html
