一 多執行緒 硬體基礎

2022-09-30 10:15:10 字數 3390 閱讀 6233

目錄1.2快取一致性協議

1.3寫緩衝佇列與無效化佇列

處理器的處理能力要遠遠高於主記憶體dram的讀寫能力。進行一次主記憶體的讀寫所需要的時間,處理器可能足夠處理上百條指令。為了彌補處理器與主記憶體巨大的效率差距,處理器的設計者們引入了快取記憶體cache。

快取記憶體的容量遠小於主記憶體,但是讀取速率要遠遠高於主記憶體。有了快取記憶體後,處理器如果想要讀取資料就可以直接從快取記憶體中讀取,而不用從主記憶體中讀取。快取記憶體中以乙個類似於拉鍊雜湊表的形式儲存主記憶體中的內容副本,其key是記憶體位址,value是該記憶體位址所儲存的值,或者將要寫入記憶體的的值。其結構包含若干桶,每個桶又包含若干快取條目。

1.1.1快取條目

每乙個快取條目又被劃分成tag、data block、flag三個部分

data block又被稱為快取行是與記憶體進行資料交換的最小單元,其中儲存著從記憶體中讀取的資料或者將要寫入記憶體中的資料。乙個快取行中可能儲存多個變數的資料。

tag包含了與快取行中資料相對應的記憶體位址的部分資訊。

flag表示快取行的狀態資訊。

1.1.2快取命中與快取未命中

處理器執行記憶體訪問操作時會將對應的記憶體位址解碼,其結果包含index、tag、offset。index用於定位桶,tag通過與快取條目的tag對比後定位相應的快取條目,offset則是該變數所在快取行中的偏移量也就是儲存該變數的起始位置。如果通過如上規則能夠在快取記憶體中找到對應的快取行並且該快取行所在的快取條目的flag值表示是有效的,則稱這次記憶體訪問操作產生的快取命中,否則稱這次記憶體訪問操作產生了快取未命中。

快取未命中也分為讀未命中和寫未命中。如果發生了讀未命中則處理器會從主記憶體中讀取資料並存入相應的快取行之中,這個過程會造成處理器停頓而不能執行其他指令影響處理器的效能。因此我們希望能夠盡可能減少快取未命中,但是由於快取的容量遠小於記憶體的容量,所有快取未命中是不可避免的。

多執行緒共同操作同乙個變數的情況下,執行這些執行緒的處理器都會在其快取中儲存該變數的副本。如果其中乙個執行緒更新了該變數在快取中的副本,那麼其他執行緒是如果察覺並同步的呢?如果其他執行緒並未同步變數的更新,並且讀取該變數的話就會得到老的資料。為解決這種情況,引入了以中通訊機制:快取一致性協議

mesi協議將快取條目的狀態劃分為:modified、exclusive、shared、invalid四種。並定義了一組訊息用於協調各個處理器的讀寫記憶體操作,如下表所示。處理器要執行讀寫操作時會向匯流排bus中傳送特定的請求訊息,其他處理器嗅探(snoop也稱攔截)匯流排中由其他處理器所發出的請求訊息,並在一定條件下向匯流排中回覆相應的響應訊息。

訊息名訊息型別

描述read

請求通知其他處理器,主記憶體當預處理器正準備讀取某個資料。該訊息包含待讀取資料的記憶體位址

read response

相應該訊息相應read訊息,其中包含被請求讀取的資料,有可能是來自與其他處理器中的快取記憶體提供的,也可能是主記憶體提供的

invalidate

請求通知其他處理器將其快取記憶體中指定記憶體位址對應的快取條目的狀態flag值置為i,即刪除指定記憶體位址的副本資料(邏輯刪除)

invalidate acknowledge

響應接受到invalidate訊息的處理器必須回覆該訊息,表示刪除了其快取記憶體上相應的副本資料

read invalidate

請求該訊息是read訊息和invalidate訊息的組合。作用在通知其他處理器當預處理器準備更新乙個資料(read-modify-write)接受到該訊息的處理器必須回覆read response訊息和invalidate訊息

writeback

請求該訊息包含需要寫入主記憶體的資料及其對應的記憶體位址

如果你仔細思考寫記憶體操作的過程便會發現,快取一致性協議雖然保證了每個處理器上關於同乙個共享變數的快取一致性。但是為了保證快取一致性付出了效能下降的代價,因為當處理器執行寫操作時候必須等待其他所有處理刪除他們快取上相應的快取條目,並且接受到其他所有處理器回覆的invalidate acknowledge或read response後才能將資料寫入快取記憶體。為了減少這種由於等他其他處理器回覆訊息所造成的延遲,硬體的設計者們引入了寫緩衝器和無效化佇列。

引入寫緩衝器後寫記憶體操作的流程是:如果相應的快取條目的狀態是e或者m,則直接寫入快取而無序傳送任何訊息;如果相應快取條目的狀態是s,則先將要寫的資料與對應的記憶體位址存入寫緩衝器中的條目之中,並傳送invalidate訊息;如果相應快取條目的狀態是i(稱為寫未命中,開銷比較大,因為read訊息可能會造成讀記憶體操作),則先將要寫的資料與對應的記憶體位址存入寫緩衝器中的條目之中,並傳送read invalidate訊息。當處理器將相應資料寫入寫緩衝器之後,對於執行寫的處理器來說便認為寫操作已經完成,因此不必等待invalidate acknowledge或read response訊息可以繼續執行其他指令。當執行寫操作的處理器接受到其他所有處理器針對同乙個快取條目的invalidate acknowledge或read response訊息時,該處理器會把針對相應記憶體位址的寫操作結果寫入相應的快取行中,此時對於寫操作以外的其他處理器來說寫操作才算完成(因為此時其他處理器可以通過快取一致性協議讀取到這次寫操作後的最新值)。

引入無效化佇列後,處理器在接受到invalidate並不刪除相應位址的快取條目,而是將訊息存入無效化佇列後就回覆invalidate acknowledge訊息,從而減少執行寫操作處理器等待的時間。有些處理器可能沒有無效化佇列(x86)

1.3.1儲存**

引入寫緩衝器之後,執行寫操作並且最新的資料還儲存的寫緩衝器而沒有寫到相應的快取行,如果此時執行該處理器執行讀操作並直接讀取快取行中的資料的話便會讀取到乙個舊的值。因此,有了寫緩衝器,處理器在執行讀操作時會先查詢寫緩衝器,如果寫緩衝器存在相應的條目則直接把值返回,如果沒有再去快取記憶體中讀取。這種直接從寫緩衝器中讀取資料來實現記憶體讀操作的技術被稱為儲存**store forwarding(可以理解為本應儲存在記憶體上的資料被**到了寫緩衝器上)

併發基礎之一 多執行緒synchronized

public class demo 簡便的寫法一 public void test 簡便的寫法二 public synchronized void test 在這裡的排序也是有講究的,synchronized雖然在 一 二這裡起到的作用相同。但是synchronied如果只需要一部分 需要上鎖,那麼...

(一)多執行緒之執行緒理論

一 什麼是執行緒 在傳統作業系統中,每個程序有乙個位址空間,而且預設就有乙個控制線程。執行緒顧名思義,就是一條流水線工作的過程 流水線的工作需要電源,電源就相當於cpu 而一條流水線必須屬於乙個車間,乙個車間的工作過程是乙個程序,車間負責把資源整合到一起,是乙個資源單位,而乙個車間內至少有一條流水線...

Python多執行緒(一) 多執行緒的建立

在python3中,多執行緒主要使用threading模組 首先,來看乙個單任務模式的例子 import datetime,time defeat hotpot food for i in range 2 print datetime.datetime.now strftime x eat str ...