開始搞起來吧。這周先把多線程的各個細節(jié)搞好他。最好能整理出文字性的東西吧。現(xiàn)在開始第一天吧~
-
CPU多級緩存
-
一級緩存太貴,所以有有了二級、三級緩存
image.png
-
-
為啥要cache
image.png -
cache容量有限,命中率低,為啥還要他。
image.png -
緩存一致性 MESI
image.png
開始搞cpu、內(nèi)存、緩存之間的關(guān)系
- 絕大多數(shù) 的內(nèi)存訪問都需要通過層層的緩存來進行
- CPU正常情況下不能直接訪問內(nèi)存,物理決定。只能通過多級緩存來訪問內(nèi)存
- 先來個籠統(tǒng)一點的概念
- 緩存段,一段和緩存大小對其的內(nèi)存。
如果只是讀的情況
這種情況下,任意時刻,緩存中緩存段的內(nèi)容和內(nèi)存中對應(yīng)的內(nèi)容是一致的。
- cpu首先發(fā)出讀指令,把內(nèi)存地址給到cache
- cache會檢查是否有這個地址對應(yīng)的緩存段,如果沒有,會從內(nèi)存(或者更下一級,二級之類的緩存)中把這一個緩存段全部存到一級緩存中。
- 數(shù)據(jù)被加在到一級緩存后,cpu就可以正常讀取了
如果考慮寫的情況
記住一條:當所有臟數(shù)據(jù)都被回寫后,任一級別緩存中所有緩存段的數(shù)據(jù)和內(nèi)存中對應(yīng)的數(shù)據(jù)是一致的。
- 寫的情況,分為直寫(write-through)和回寫(write-back)
- 直寫:如果對應(yīng)緩存中的段被更新了,那他的下一級緩存或者內(nèi)存也應(yīng)該同步被更新。
- 回寫:如果對應(yīng)緩存中的段被更新了,不會立即被寫到下一級緩存或者內(nèi)存,而是被標記為了臟段。臟段會在特定的時刻(具體啥時候下面會詳細說)觸發(fā)回寫。也就是說,臟段在被丟棄的時候,總是要先進行一次回寫。
- 這個地方就沒有任何時刻了,因為回寫模式有臟數(shù)據(jù)的存在。
- 雖然直寫看上去更簡單,但是回寫模式可以避免對同一片地址的反復操作,可以一次性寫一大片內(nèi)存。
一致性協(xié)議
上面扯的那些都是在只有一組緩存的情況下,如果有多個cpu對應(yīng)多組緩存,如果某一組緩存段對應(yīng)的內(nèi)存地址中的數(shù)據(jù)被另一個cpu給修改了,會發(fā)生什么。
- 那啥,很遺憾的是,如果被其他的cpu給修改了,另外的緩存是無法得知這一更改的,這就破壞了一致性。
- 為啥不是多核cpu只對應(yīng)一組緩存呢。
- 當然是效率問題啦,并發(fā)情況下出現(xiàn)問題不都是因為效率問題導致的嗎。
- 因為在每一個時鐘或者指令周期,都只能有一個cpu通過緩存對內(nèi)存進行操作,其他的cpu就進入了等待。流水線就產(chǎn)生了冒泡。會極大浪費硬件資源~
- 所以引入多組緩存,使他們用起來的效果像只有一組緩存一樣,這個協(xié)議就是保持了多組緩存之間的一致性。
- 這個緩存一致性協(xié)議有很多種,最常用的是窺探snooping協(xié)議。
- 內(nèi)存在這里是共享資源,所有cpu對于內(nèi)存的操作都要經(jīng)過仲裁:
- 所有對于內(nèi)存的操作都經(jīng)過同一條總線,所有的緩存組都掛在這個總線上。
- 緩存不只有在與內(nèi)存發(fā)生數(shù)據(jù)交換的時候才和總線打交道,他會無視無可關(guān)注其他處理器對于內(nèi)存的操作。
- 當一個處理器通過緩存執(zhí)行了對于內(nèi)存的修改,其他的緩存組就可以窺探到這一個操作,使自己的緩存中對應(yīng)的緩存段失效或者更新。
- 內(nèi)存在這里是共享資源,所有cpu對于內(nèi)存的操作都要經(jīng)過仲裁:
MESI緩存一致性協(xié)議
- 上面說的那種方式,在直寫模型中沒有任何問題,但如果到了回寫模型,就會有問題了。
- 有可能在某一組緩存中已經(jīng)產(chǎn)生了臟數(shù)據(jù),但是此刻并沒有發(fā)生回寫,所以其他內(nèi)存組沒辦法知道這一變化,還是拿了內(nèi)存中的數(shù)據(jù)。
- 這時候只需要做的是,在產(chǎn)生臟數(shù)據(jù)之前,要把這一變化sync到其他的緩存組。這就是MESI協(xié)議啦。
-
MESI是Modified、Exclusive、Shared、Invalid的首字母縮寫,代表四種緩存狀態(tài)。下面就詳細說一下這四種狀態(tài)。
- Invalid 失效緩存段,這種狀態(tài)下可以認為是緩存中沒有這個內(nèi)存地址對應(yīng)的緩存段。
- Shared 共享緩存段。是一份和主存中一摸一樣的拷貝。這時候只能讀不能寫。多組緩存段都擁有對于這個數(shù)據(jù)的拷貝。
- Exclude 獨占緩存段。有一份與主存一摸一樣的拷貝。區(qū)別在于其他緩存段不能同時持有他,當某個緩存段處于這一狀態(tài),其他緩存段中,對應(yīng)統(tǒng)一內(nèi)存地址的緩存段就變?yōu)榱薎nvalid狀態(tài)。
- Modified 修改緩存段。此時緩存段的狀態(tài)是臟段,其他處理器緩存中的拷貝都變?yōu)镮nvalid。如果此段緩存要失效或被丟棄,需要把數(shù)據(jù)回寫到內(nèi)存。
-
好啦,上面比比了那么多,一開始所說的“一組緩存在修改前,如何通知到其他緩存的問題”已經(jīng)得到了解決。
- 只有在M或者E狀態(tài)下(獲取了獨占權(quán))的緩存才能被進行寫操作,如果沒有獲取到獨占權(quán),就要通知總線上的其他緩存,此時其他處理器緩存中對應(yīng)的數(shù)據(jù)就變?yōu)榱薎nvalid狀態(tài)。
- 如果有其他處理器想讀這塊內(nèi)存,那么M狀態(tài)下寫的數(shù)據(jù)就會被寫回到內(nèi)存,這時候就變成了Shared狀態(tài)。
1.在多核系統(tǒng)中,讀取某個緩存段,實際上會牽涉到和其他處理器的通訊,并且可能導致它們發(fā)生內(nèi)存?zhèn)鬏?。寫某個緩存段需要多個步驟:在你寫任何東西之前,你首先要獲得獨占權(quán),以及所請求的緩存段的當前內(nèi)容的拷貝(所謂的“帶權(quán)限獲取的讀(Read For Ownership)”請求)。
2.盡管我們?yōu)榱艘恢滦詥栴}做了額外的工作,但是最終結(jié)果還是非常有保證的。即它遵守以下定理,我稱之為:MESI定律
- 在所有的臟緩存段(M狀態(tài))被回寫后,任意緩存級別的所有緩存段中的內(nèi)容,和它們對應(yīng)的內(nèi)存中的內(nèi)容一致。此外,在任意時刻,當某個位置的內(nèi)存被一個處理器加載入獨占緩存段時(E狀態(tài)),那它就不會再出現(xiàn)在其他任何處理器的緩存中。



