① 計算機組成原理之緩存行 cacheLine
緩存行:64位元組;緩存行越大,局部空間效率高,讀取時間慢;反之局部空間效率低讀取速度快,所以折中選擇了64個位元組;
如何保證CPU中不同L1緩存、L2緩存的 緩存一致性?
MESI緩存一致性協議, 因特爾CPU的協議
其他的緩存一致性協議有:
MSI/MOSI/Synapse/Firefly/Dragon
L1:CPU一級緩存;
L2:CPU二級緩存;
L3:CPU三級緩存;
其中 L3 是計算 CPU共享的,L1、L2是CPU中 核 獨享的;
緩存一致性的實現:如上圖
如果左側核的X值在L1中被修改了----modified,此時會有通知到右側的核 的X為---invalid;
之後,右側再讀取X值時發現無效會往上層查詢有效數據;
為了減少 CPU 中緩存數據被不同的 核 讀取,程序設計中有一個 RingBuffer 環形緩存,在實際存儲變數 INITAL_CURSOR_VALUE 前後都增加了7個變數,long類型的長度時8位元組;CPU在讀取數據時會修改的變數只有 INITAL_CURSOR_VALUE ,數據只會被其中一個核讀取,就不會出現使用 MESI緩存一致性協議 去解決緩存一致性導致的耗時問題;
除了上述方式,JDK1.8中 使用了註解的方式強制讓一個變數占據一個緩存行;
@sun.misc.Contented
② 緩存一致性
在現代的 CPU(大多數)上,所有的內存訪問都需要通過層層的緩存來進行。CPU 的讀 / 寫(以及取指令)單元正常情況下甚至都不能直接訪問內存——這是物理結構決定的;CPU 都沒有管腳直接連到內存。相反,CPU 和一級緩存(L1 Cache)通訊,而一級緩存才能和內存通訊。大約二十年前,一級緩存可以直接和內存傳輸數據。如今,更多級別的緩存加入到設計中,一級緩存已經不能直接和內存通訊了,它和二級緩存通訊——而二級緩存才能和內存通訊。或者還可能有三級緩存。
緩存是分「段」(line)的,一個段對應一塊存儲空間,大小是 32、64或128位元組,每個緩存段知道自己對應什麼范圍的物理內存地址。
當 CPU 看到一條讀內存的指令時,它會把內存地址傳遞給一級數據緩存。一級數據緩存會檢查它是否有這個內存地址對應的緩存段。如果沒有,它會把整個緩存段從內存(或者從更高一級的緩存,如果有的話)中載入進來。是的,一次載入整個緩存段,這是基於這樣一個假設:內存訪問傾向於本地化(localized),如果我們當前需要某個地址的數據,那麼很可能我們馬上要訪問它的鄰近地址。一旦緩存段被載入到緩存中,讀指令就可以正常進行讀取。
如果我們只處理讀操作,那麼事情會很簡單,因為所有級別的緩存都遵守以下規律—— 在任意時刻,任意級別緩存中的緩存段的內容,等同於它對應的內存中的內容。 。
一旦我們允許寫操作,事情就變得復雜一點了。這里有兩種基本的寫模式:直寫(write-through)和回寫(write-back)。直寫更簡單一點:我們透過本級緩存,直接把數據寫到下一級緩存(或直接到內存)中,如果對應的段被緩存了,我們同時更新緩存中的內容(甚至直接丟棄),就這么簡單。這也遵守前面的定律: 緩存中的段永遠和它對應的內存內容匹配。
回寫模式就有點復雜了。緩存不會立即把寫操作傳遞到下一級,而是僅修改本級緩存中的數據,並且把對應的緩存段標記為「臟」段。臟段會觸發回寫,也就是把裡面的內容寫到對應的內存或下一級緩存中。回寫後,臟段又變「干凈」了。當一個臟段被丟棄的時候,總是先要進行一次回寫。回寫所遵循的規律有點不同。 當所有的臟段被回寫後,任意級別緩存中的緩存段的內容,等同於它對應的內存中的內容。
換句話說,回寫模式的定律中,我們去掉了「在任意時刻」這個修飾語,代之以弱化一點的條件:要麼緩存段的內容和內存一致(如果緩存段是干凈的話),要麼緩存段中的內容最終要回寫到內存中(對於臟緩存段來說)。
只要系統只有一個 CPU 核在工作,一切都沒問題。如果有多個核,每個核又都有自己的緩存,那麼我們就遇到問題了,因為如果一個 CPU 緩存了某塊內存,那麼在其他 CPU 修改這塊內存的時候,我們希望得到通知。系統的內存在各個 CPU 之間無法做到與生俱來的同步,我們需要一個大家都能遵守的方法來達到同步的目的。
緩存一致性協議有多種,但是日常處理的大多數計算機設備使用的都屬於「窺探(snooping)」協議。
窺探」背後的基本思想是,所有內存傳輸都發生在一條共享的匯流排上,而所有的處理器都能看到這條匯流排:緩存本身是獨立的,但是內存是共享資源,所有的內存訪問都要經過仲裁(arbitrate):同一個指令周期中,只有一個緩存可以讀寫內存。窺探協議的思想是,緩存不僅僅在做內存傳輸的時候才和匯流排打交道,而是不停地在窺探匯流排上發生的數據交換,跟蹤其他緩存在做什麼。所以當一個緩存代表它所屬的處理器去讀寫內存時,其他處理器都會得到通知,它們以此來使自己的緩存保持同步。只要某個處理器一寫內存,其他處理器馬上就知道這塊內存在它們自己的緩存中對應的段已經失效。
在直寫模式下,這是很直接的,因為寫操作一旦發生,它的效果馬上會被「公布」出去。但是如果混著回寫模式,就有問題了。因為有可能在寫指令執行過後很久,數據才會被真正回寫到物理內存中——在這段時間內,其他處理器的緩存也可能會傻乎乎地去寫同一塊內存地址,導致沖突。在回寫模型中,簡單把內存寫操作的信息廣播給其他處理器是不夠的,我們需要做的是,在修改本地緩存之前,就要告知其他處理器。
MESI 是四種緩存段狀態的首字母縮寫,任何多核系統中的緩存段都處於這四種狀態之一。
從CPU讀寫角度來說:
上圖的切換解釋:
緩存的一致性消息傳遞是要時間的,這就使其切換時會產生延遲。當一個緩存被切換狀態時其他緩存收到消息完成各自的切換並且發出回應消息這么一長串的時間中CPU都會等待所有緩存響應完成。可能出現的阻塞都會導致各種各樣的性能問題和穩定性問題。
比如你需要修改本地緩存中的一條信息,那麼你必須將I(無效)狀態通知到其他擁有該緩存數據的CPU緩存中,並且等待確認。等待確認的過程會阻塞處理器,這會降低處理器的性能。因為這個等待遠遠比一個指令的執行時間長的多。
為了避免這種CPU運算能力的浪費,Store Bufferes被引入使用。處理器把它想要寫入到主存的值寫到緩存,然後繼續去處理其他事情。當所有失效確認(Invalidate Acknowledge)都接收到時,數據才會最終被提交。
執行失效也不是一個簡單的操作,它需要處理器去處理。另外,存儲緩存(Store Buffers)並不是無窮大的,所以處理器有時需要等待失效確認的返回。這兩個操作都會使得性能大幅降低。為了應付這種情況,引入了失效隊列——對於所有的收到的Invalidate請求,Invalidate Acknowlege消息必須立刻發送,Invalidate並不真正執行,而是被放在一個特殊的隊列中,在方便的時候才會去執行,處理器不會發送任何消息給所處理的緩存條目,直到它處理Invalidate。
③ volitate 原理
volatile保證多線程可見性,volatile修飾的變數不會引起上下文切換和調度
cpu緩存,cpu運算速度與內存讀寫不匹配,因為cpu運算速度比內存讀寫快的多
從主內存中獲取或者寫入數據會花費很長時間,現在大多數cpu都不會直接訪問內存,而是訪問cpu緩存,cpu緩存是cpu與主內存之間的臨時存儲器,容量小,交換速度快,緩存中的數據是內存中的一小部分數據,是cpu即將訪問的。當cpu調用大量數據時候,就先從緩存中讀取從而加快讀取速度
按照讀取順序與cpu結合的緊密程度,cpu緩存分為
一級緩存:L1位於cpu內核旁邊,是與cpu結合最為緊密的cpu緩存
二級緩存:L2分為內部和外部兩種晶元,內部晶元二級緩存運行速度與主頻相同,外部晶元二級緩存運行速度則只有主頻的一半
三級緩存,只有高端的cpu才有
每一級緩存中所存儲的數據都是下一級緩存中存儲的數據的一部分
cpu要讀取一個數據的時候,首先從一級緩存中查找,如果沒有就從二級中查找,如果還沒有就從三級緩存中或者是內存總進行查找,一般來說,每級緩存的命中率大概有0.8左右,也就是全部數據量的0.8可以在一級緩存中查到,只有剩下的0.2總數據量從二級緩存中或者是三級緩存或者是內存中讀取
緩存行:緩存是分line的,一個段對應一個緩存行,是cpu緩存種可分配的最小存儲單元,通常是64位元組:當cpu看到一條讀取內存的指令的時候,會把內存地址傳遞給一級緩存,一級緩存會檢查它是否有這個內存地址對應的緩存段,如果沒有就把整個緩存段從內存共或者更高級的緩存種載入進來。
cpu執行計算的過程為:程序和數據被載入到主內存中,指令和數據被載入到cpu緩存中,cpu執行指令將結果寫入cpu緩存中,cpu緩存中的數據寫回到主內存中,但是這種方式僅限於單核cpu的時候
如果伺服器是多核cpu呢,
多核處理器中主內存核處理器一樣是分開的,這時候,L3作為統一的高速緩存共享,處理器1擁有自己的L1 L2
這個時候當核0讀取了一個位元組根據局部性原理,與他相鄰的位元組同樣會被讀入核0的緩存中
核3也讀取了同樣的一個位元組,根據局部性原理,與他相鄰的位元組同樣會被讀入到核3的數據中
此時,核0和核3的緩存中擁有同樣的數據
核0修改了那個位元組之後,被修改後那個位元組被回寫到了核0的緩存中,但是該信息並沒有回寫到主內存
當核3訪問該數據的時候,造成該數據不同步
為了解決這個問題**,當一個cpu修改緩存中的位元組的時候,**伺服器中其他cpu的會被通知他們的緩存將是為無效,這樣核1在修改緩存中的數據的時候,核3會發現自己的緩存中的數據已經無效,核0將自己的寫回到主內存中,然後核3將重新讀取該數據
將代碼轉化為匯編指令的時候發現在匯編指令add之前有一個lock指令,lock指令就是關鍵。
lock指令的作用:在修改內存的時候使用lock前綴指令調用加鎖的讀修改寫操作,保證多處理器系統總處理器之間進行可靠的通訊
1.鎖匯流排,其他cpu對內存的讀寫請求會被阻塞,直到鎖釋放,不過實際候來的處理器都採用了緩存緩存代替鎖匯流排,因為匯流排開銷過大,鎖匯流排的時候其他cpu沒辦法訪問內存
2.lock後的寫操作會回寫已經修改的數據,同時讓其他cpu相關緩存行失效,從而重新從內存中載入最新的數據
3.不是內存屏障卻能完成內存屏障的功能,阻止屏障兩邊的指令重排序
嗅探式的緩存一致性協議:所有內存的傳輸都發生在一條共享的匯流排上,而所有的處理器都能看到這條匯流排,緩存本身是獨立的,但是內存是共享的。所有的內存訪問都要進行仲裁,即同一個指令周期種只有一個cpu緩存可以讀寫數據。cpu緩存不僅在內存傳輸的時候與匯流排打交道,還會不斷的在嗅探匯流排上發生數據交換跟蹤其他緩存在做什麼,所以當一個cpu緩存代表它所屬的處理器讀寫內存的時候,其他的處理器都會得到通知(主動通知),他們以此使自己的緩存保存同步。只要某個處理器寫內存,其他處理器就馬上直到這塊內存在他們的緩存段種已經失效。。
MESI協議是緩存一致性協議,在MESI協議中每個緩存行有四個狀態,Modified修改的,表示這行數據有效,數據被修改了和內存中的數據不一致,數據只存在當前cache中,Exclusive獨有的,這行數據有效,數據和內存中的數據一致,數據只存在在本cache中,Shared共享的,這行數據有效,數據和內存中的數據一致,數據存在很多cache中,Invalid這行數據無效,這里的Invalid shared modified都符合我們的嗅探式的緩存一致性協議,但是Exclusive表示獨占的,當前數據有效並且和內存中的數據一致,但是只在當前緩存中,Exclusive狀態解決了一個cpu緩存在讀寫內存的之前我們要通知其他處理器這個問題,只有當緩存行處於Exclusive和modified的時候處理器才能寫,也就是說只有在這兩種狀態之下,處理器是獨占這個緩存行的,當處理器想寫某個緩存行的時候,如果沒有獨占權就必須先發送一條我要獨占權的請求給匯流排,這個時候會通知處理器把他們擁有同一緩存段的拷貝失效,只要在獲得獨占權的時候處理器才能修改數據並且此時這個處理器直到這個緩存行只有一份拷貝並且只在它的緩存里,不會有任何沖突,反之如果其他處理器一直想讀取這個緩存行(馬上就能直到,因為一直在嗅探匯流排),獨占或已修改的緩存行必須要先回到共享狀態,如果是已經修改的緩存行,還要先將內容回寫到內存中。
volatile變數的讀寫
工作內存其實就是cpu緩存,當兩條線程同時操作主內存中的一個volatile變數時候,A線程寫了變數i,此時A線程發出lock指令,發出的lock指令鎖匯流排或者鎖緩存行,同時線程b的高速緩存中的緩存行內容失效,線程A想內存中回寫最新的i。當線程B讀取變數的時候,線程發現對應地址的緩存行被鎖了等待鎖釋放,鎖的一致性協議會保證它讀取到最新的值。
④ 有誰知道cache的發展過程
縱觀PC系統和CPU二十年的發展,隨著半導體加工工藝水平的不斷提高,CPU和存儲器的性能都有了很大的提高。
CPU頻率的提高,必然要求系統中存儲器的存取速度要提高,還要求其容量要增大。主存儲器DRAM容量的提高還是比較快的,但是DRAM讀取時間的提高卻很慢。從而在速度上與CPU主頻的提高產生了極不相配的情況,這樣會影響整個系統的性能。二十年來,CPU設計的問題之一就是解決高速CPU和低速DRAM之間的平衡或匹配問題,以求系統性能的整體提高。
在它們之間加入高速緩沖存儲器Cache,就是這個問題的解決方案之一。
Cache隨CPU的發展而不斷改變,可以概括為:從無到有,由小到大,先外後內,縱深配備,軟硬兼施。初期的CPU沒有Cache,在80386時期出現外部Cache;80486時期開始有內部僅8kB的Cache。Cache的分級也由L1和L2級,發展到L0和L3級的縱深配備;Cache的大小由當初的8kB,直到Merced的1~2MB。為了更好地利用Cache,還專門配有緩存控制指令。
本文回顧了在過去的二十年中,Cache技術的發展歷程,並對PC其它設備使用Cache技術作了簡單陳述。 PC初期無需Cache在八十年代初,由於CPU主頻很低,DRAM的存取時間甚至快於CPU存取時間,因此無需Cache。例如,當時PC機採用8088CPU,系統主頻為4.77MHz,一個基本匯流排周期為4拍,即840ns。此時64kB的DRAM存取周期200ns,造成DRAM等待CPU的執行的局面,無需Cache。
在PC/AT機採用80286CPU後,系統主頻增加到10MHz,1個基本匯流排周期為2拍,即200ns。此時必須用讀取時間為100ns的DRAM。在採用25MHz的80386DX時,一個基本匯流排周期為2拍,即80ns,當時已沒有速度相匹配的DRAM可用。解決方案有2種:一種是在基本匯流排周期中插入等待,降低CPU的處理能力;另一種是採用內部和外部Cache,使用SRAM晶元以提高存儲器的讀取速度。80386沒有L1 Cache80386初期主頻為20MHz。Intel公司十分重視80386的設計製造,把它定位於「新一代個人電腦架構」,想把一些新技術設計在晶元中。但由於當時工藝所限,內置高速緩存的晶元體積過大,造成成本上升,同時工期有限,幾經權衡,最後決定在80386晶元不設置高速緩沖存儲器,可以生產另外的Cache,以配合80386運作。
盡管人們意識到CPU主頻的增加與內存DRAM存取時間過慢的矛盾已愈加突出,但因條件所限,80386內部沒有L1 Cache,只有外部的Cache。80486出現Cache80486是由80386CPU加80387數字協處理器以及8kB Cache構成。
當CPU的時鍾頻率繼續增加時,外部Cache的SRAM晶元速度也要相應提高,這樣會增加系統成本,為此在設計80486時採用了內部Cache。
80486晶元內由8kB的Cache來存放指令和數據。同時,80486也可以使用處理器外部的第二級Cache,用以改善系統性能並降低80486要求的匯流排帶寬。Cache可以工作在80486所有的操作模式:實地址模式、保護模式和X86模式。對Cache的操作是由系統自動進行的,對程序員透明。而在多處理器系統中,可能要求系統軟體的干預。對於一般的計算機,在系統CMOS設置中均有Cache使用模式的設置。
80486內部Cache是一個4路組相聯Cache,在主存儲器中給定單元的數據能夠存儲在Cache內4個單元中的任何一個。這種4路相聯方式是高命中率的全相聯Cache和快速的直接映像Cache的一種折衷,因而能進行快速查找並獲得高的命中率。Peutium的分離L1 Cache和L2 CachePentium處理器採用了超標量結構雙路執行的流水線,有分支預測技術。
由於Pentium設計有2條並行整數流水線,可同時執行2條命令。整數單元的潛在處理能力實際可增加一倍,處理器也需要對命令和數據進進雙倍的訪問。為使這些訪問不互相干涉,Intel把在486上共用的內部Cache,分成2個彼此獨立的8kB代碼Cache和8kB數據Cache,這兩個Cache可以同時被訪問。這種雙路高速緩存結構減少了爭用Cache所造成的沖突,提高了處理器效能。Pentium的Cache還採用了回寫寫入方式,這同486的貫穿寫入方式相比,可以增加Cache的命中率。此外,還採用了一種稱為MESI高速緩存一致性協議,為確保多處理器環境下的數據一致性提供了保證。Pentium Pro內嵌式L2 Cache為使Pentium Pro的性能超過Pentium,必需使用創新的設計方法。Pentium Pro使用了新的超標量和級流水線技術,包括無序執行、動態分支預測和推測執行的動態執行新技術。它可以使CPU在一個時鍾周期執行3條微操作。CPU並行處理速度的加快,意味著它同時處理指令和數據的數量增加,為不使CPU處於等待狀態,需要重新設計Cache。
Pentium Pro在片內第一級Cache的設計方案中,使指令Cache與數據Cache分別設置。指令Cache的容量為8kB,採用2路組相聯映像方式。數據Cache的容量也為8kB,但採用4路組相聯映像方式。Pentium Pro採用MESI(修改、排他、共享、作廢)協議來維持Cache和主存儲器之間的一致性。通常,人們總以為,像Pentium Pro這樣的3路超標量結構的微處理器會採用更大容量的片內第一級Cache和更大的第二級Cache。然而,Intel公司的設計者卻選擇了另一條設計思路——設計一種Cache存儲階層結構,使得能夠從一個Cache流動到另一個Cache,而不用阻塞執行。
Pentium Pro採用了內嵌式或稱捆綁式L2Cache,大小為256kB或512kB。此時的L2已經用線路直接連到CPU上,益處之一就是減少了對急劇增多L1 Cache的需求。L2 Cache還能與CPU同步運行。即當L1 Cache不命中時,立刻訪問L2 Cache,不產生附加延遲。為進一步減少因要訪問的信息不在高速緩沖中時所帶來的性能損失,Pentium Pro的L1和L2都設計成非鎖定型。即當哪個Cache中沒有CPU所需的信息時,它不妨礙後面訪問Cache的處理過程。Cache可以直接處理最多4次的Cache缺頁情況,藉助CPU的內存有序緩沖區可以順序保存最多12次的內存訪問。非鎖定型Cache適用於Pentium Pro的亂序執行核心,因為在可能引發流水線延遲的長等待內存操作期間,這些Cache可以讓CPU繼續運行。
Pentium Pro的如此捆綁封裝,帶來器件成本提高。一方面專用的L2 cache晶元成本高,另一方面兩個不同功能的晶元只有放在一起聯結後才能最後測試其性能的完整性。而當其中有一個有缺陷時,兩個晶元都被報廢。在以後的Pentium Pro產品中,又將L2 Cache從晶元中去掉。Pentium MMX容量增大的L1和L2CachePentium MMX是能運行多媒體指令MMX的高能奔騰處理器。Pentium MMX具有改進的分支預測和增強型流水線技術,並將L1 Cache容量增加到32kB,L2 Cache為512kB。
Pentium MMX的片內L1數據和指令的Cache,每個增到16kB,4路相聯。較大的獨立內部Cache、減少平均內存存取時間,同時提供對近期所用指令和數據的快速存取,性能因此得到提高。數據Cache支持採用回寫方式更新內存。
由於CacheL1容量的增大,使當時的應用程序運行速度提高了10%左右。PentiumⅡ設有雙獨立匯流排連接L2 CachePentiumⅡ是Pentium Pro的改進型,具有MMX指令,使用動態執行技術,採用雙獨立匯流排結構。PentiumⅡ同樣有2級Cache,L1為32kB(指令和數據Cache各16kB)是Pentium Pro的一倍。L2為512kB。
Pentium Ⅱ與Pentium Pro在L2 Cache 的不同是由於製作成本原因。L2 Cache已不在內嵌晶元上,而是與CPU通過專用64位高速緩存匯流排相聯,與其它元器件共同被組裝在同一基板上,即「單邊接觸盒」上。雙獨立匯流排結構就是:L2高速緩存匯流排和處理器至主內存(Processor-to-main-memory)的系統匯流排。 PentiumⅡ處理器可以同時使用這兩條匯流排,與單一匯流排結構的處理器相比,該處理器可以進出兩倍多的數據,可允許 PentiumⅡ處理器的L2高速緩存比Pentium處理器的L2高速緩存要快1倍。隨著 PentiumⅡ處理器主頻的提高,L2高速緩存的速度也將加快。最後,流水線型系統匯流排可允許同時並行傳輸,而不是單個順序型傳輸。改進型的雙重獨立匯流排結構,可以產生超過與單匯流排結構三倍帶寬的性能。另外,在PentiumⅡ中,採用了ECC技術,此技術應用到二級高速緩存中,大大提高了數據的完整性和可靠性。
為開發低端市場,曾在 PentiumⅡ的基板上除去L2,犧牲一些性能,製造廉價CPU。這就是最初的Celeron處理器。以後的Celeron仍加有較小的片上L2 Cache,其大小為128kB。PentiumⅢ的L2 Cache增大PentiumⅢ也是基於Pentium Pro結構為核心,在原有MMX多媒體指令的基礎上,又增了70多條多媒體指令。它使用動態執行技術,採用雙獨立匯流排結構。
PentiumⅢ具有32kB非鎖定L1 Cache和512kB非鎖定L2 Cache。L2可擴充到1~2MB,具有更合理的內存管理,可以有效地對大於L2緩存的數據塊進行處理,使CPU、Cache和主存存取更趨合理,提高了系統整體性能。在執行視頻回放和訪問大型資料庫時,高效率的高速緩存管理使PⅢ避免了對L2 Cache的不必要的存取。由於消除了緩沖失敗,多媒體和其它對時間敏感的操作性能更高了。對於可緩存的內容,PⅢ通過預先讀取期望的數據到高速緩存里來提高速度,這一特色提高了高速緩存的命中率,減少了存取時間。Merced設有L0即將推出的第7代處理器Merced主頻可達1GHz。很明顯,對Cache的要求更高了。為此,lntel本著「大力提高執行單元和緩存間數據交換速度」的思想,在晶元內開發新的Cache,並增加L1 Cache的容量,來平衡CPU和DRAM間的速度。
為此,在Merced的片上最接近執行單元旁再設另一處Cache,稱為L0緩存,是指令/數據分離型。由於L0Cache在物理位置上比L1離執行單元更近,布線距離的縮短,使它與執行單元間的數據交換速度比L1還快,可以進一步提高工作主頻。
同時,還要在晶元內部配置超過1MB的大容量L1 Cache。晶元內部Cache比外部Cache更易於提升與執行單元間的數據傳送速度。內部Cache的加大,執行單元不易發生「等待」。現行的內部Cache容量僅為32kB~128kB。內部Cache容量的增加會引起晶元面積增大,提高製造成本。但大部分公司認為,由於內部Cache容量增大而導致成本的上揚,可以用製造技術來彌補。與Cache相配合的緩存控制指令為進一步發揮Cache的作用,改進內存性能並使之與CPU發展同步來維護系統平衡,一些製造CPU的廠家增加了控制緩存的指令。如Intel公司在PentiumⅢ處理器中新增加了70條3D及多媒體的SSE指令集。其中有很重要的一組指令是緩存控制指令。AMD公司在K6-2和K6-3中的3DNow!多媒體指令中,也有從L1數據Cache中預取最新數據的數據預取指令(Prefetch)。
PentiumⅢ處理器的緩存控制指令,用於優化內存連續數據流。針對數據流的應用需要對以前的Cache運作方式進行了改進,減少了一些不必要的中間環節,節省了時間,增加了CPU數據匯流排的實際可用帶寬,也提高了Cache的效率。
有兩類緩存控制指令。一類是數據據預存取(Prefetch)指令,能夠增加從主存到緩存的數據流;另一類是內存流優化處理(Memory Streaming)指令,能夠增加從處理器到主存的數據流。這兩類指令都賦予了應用開發人員對緩存內容更大控制能力,使他們能夠控制緩存操作以滿足其應用的需求。
數據預存取指令允許應用識別出所需的信息,並預先將其從主存中取出存入緩存。這樣一來,處理器可以更快地獲取信息,從而改進應用性能。為了進一步削減內存延遲,內存訪問還可以與計算機周期保持流水操作。例如,如果一個應用需要計算一些數值以供3D圖形使用,當它在計算一個值的同時就可以預取下一個需要計算的數值。
內存流優化處理指令允許應用越過緩存直接訪問主存。通常情況下,處理器寫出的數據都將暫時存儲在緩存中以備處理器稍後使用。如果處理器不再使用它,數據最終將被移至主存。然而,對於多媒體應用來就,通常不再需要使用這些數據。因此,這時將數據盡快地移到主存中則顯得至關重要。採用了PentiumⅢ處理器的內存流優化處理指令後,應用程序就能讓數據搭乘「直達快車」,直接到達主存。當數據流直接到達主存時,處理器負責維護緩存的一致性。因為這種方式避免了為數據流留出空間清空緩存的當前內容,從而也提高了緩存的利用率。
總而言之,緩存控制指令改進了進出處理器的數據據流,使處理器保持其高速率運作。通過這些指令(同時還需要一些專為其設計以使其發揮優勢的軟體),商業用戶可以在操作系統和圖形設備驅動程序中感受其性能優勢。Cache在PC中其它設備的應用Cache作為一種速度匹配技術,不僅用在提高CPU對內存的讀寫速度上,而且也用在CPU結構的其它部分和PC系統中。
PC的顯示系統中,由於3D應用的迅猛發展,大量的顯示內存使用著高速緩存技術,如前台緩存、後台緩存、深度緩存和紋理緩存等。
PC的磁碟系統中,為提高內存對磁碟(主要是硬碟)的讀寫速度,就要建立磁碟高速緩存。因為DRAM內存的存取速度對CPU來說較慢,但對磁碟的存取速度卻是很快的。這是因為磁碟存儲系統包含有磁頭的機械運動,而機械運動無法跟傳送電信號的電子速度相比。此外,磁頭中電與磁的信號轉換也對速度有影響。這樣,為了提高磁碟存取速度而採用Cache也就順理成章了。硬碟Cache無需使用高速的SRAM,它只需在內存(DRAM)中劃出一個區域,作為專用的磁碟緩沖區,採用一定的數據結構,即可實現磁碟存取的Cache技術。它的過程也是把即將訪問的數據整塊地拷貝到高速緩存區中,然後內存再到高速緩存中去逐個讀取數據。由於數據在RAM空間內部傳送要比在RAM與磁碟間傳送快得多,系統由此提高了存取速度。
硬碟的Cache可以放在常規內存中。不過,為了不佔用寶貴的用戶程序空間,通常是把它設在擴展內存或擴充內存里。硬碟Cache是由人們共知的SMARTDRIVE.EXE文件自動建立的,用戶只需在AUTOEXEC.BAT與CONFIG.SYS中加入相應的命令行就成了。
在較慢速的其它外圍設備和內存的數據交換中,在網路通訊中,都需要使用Cache技術。推而廣之,凡是在傳輸速度有較大差異的設備之間,都可以利用Cache的速度匹配技術。結束語PC中的Cache主要是為了解決高速CPU和低速DRAM內存間速度匹配的問題,是提高系統性能,降低系統成本而採用的一項技術。隨著CPU和PC的發展,20年來,現在的Cache已成為CPU和PC不可缺少的組成部分,是廣大用戶衡量系統性能優劣的一項重要指標。據預測,在21世紀初期,CPU主頻加快發展的趨勢,加上內存DRAM的存取時間也會提高,從系統的性價比考慮,Cache的配備仍然是重要的技術之一。
⑤ EMSI協議
翻譯至 https://en.wikipedia.org/wiki/MESI_protocol
EMSI是基於緩存無效化的一致性緩存協議,並且是一種最常見的支持回寫式緩存的協議。它也被稱為伊利諾伊州協議(由於其在伊利諾伊大學厄本那香檳分校被開發)。回寫式緩存和寫入式緩存相比可以節約很多的帶寬。回寫式緩存經常會存在臟狀態,而臟狀態表明了高數緩存中的數據與主存中的數據不一致。EMSI要求當緩存未命中時並且別的緩存中有該數據,那麼緩存和緩存間應該互相傳輸數據。MESI相對與MSI來說降低了與主存的交互次數,這帶來了顯著的性能提升。
MESI的四個字母分別代表了四個可以被標記在緩存行上的獨立狀態。(也就是用2bit來編碼)
當緩存行處於Modified狀態時,它表明該緩存行只存在於當前緩存中。並且這個緩存行中的數據是臟數據,也就是說這個緩存行中的數據與主存中的數據不一致。緩存被要求在未來將緩存行的數據寫於主存中,但不用立即寫入。但如果別的緩存向該緩存請求這個數據,那必須保證該數據寫入主存已經完成。當回寫回主存完成後,緩存行狀態會有Modified變為Shared狀態。
當緩存行處於Exclusive狀態時,它表明該緩存行只存在於當前緩存中,不過其中的數據與主存中的數據是一致的。當別的緩存向該緩存請求read當前緩存行時,緩存行狀態會變成Shared。或者當有write操作時,他會變成Modified狀態。
當緩存行處於Shared狀態時,它表明該緩存行可能同時存在與別的緩存中,並且其中的數據與主存中一致。這個緩存行隨時可能被丟棄(改變為Invalid狀態)。
當緩存行處於Invalid 狀態時,表明該緩存行是無效的。
對於給定的兩個緩存,以下是允許共同存在的狀態:
當一個緩存中的變數被標記為M狀態,那同樣擁有這個變數的別的緩存的緩存行會被標記為Invalid。
從一個狀態到另一個狀態的轉變有兩個重要影響因素。第一個因素是處理器發出了特殊的讀寫請求。舉個栗子:處理器A的緩存中有變數X,然後這個處理器向自己的緩存發送了對於這個變數的讀寫請求。第二個影響因素是來自別的處理器的請求,這些處理器緩存中沒有這個變數,或者它們想要更新這個變數。這些匯流排請求被一個名叫Snoopers的監聽器監聽著。
下面解釋不同種類的處理器請求和匯流排請求
處理器請求包括如下兩種:
匯流排請求包括如下五種:
如果從主存中獲取一個值需要等待的時間比通過緩存間傳值等待的時間長,那麼我們就可以說緩存間傳值可以降低緩存未命中後的讀延遲。在多核架構下,一致性主要在二級緩存間保持,但處理器仍然有三級緩存,從三級緩存中獲取未命中的變數往往快於從二級緩存。
監控操作 :
所有緩存中的變數都擁有四種狀態的有限狀態機。
對於不同輸入的狀態轉換關系和回復如下表1.1和1.2
只有寫操作發生在Modified或Exclusive狀態的緩存行時,才緩存才不需要做額外操作。如果狀態為Shared的緩存行被寫入,那麼首先別的緩存需要無效它們的緩存行。這個由一個叫 Request For Ownership (RFO) .的廣播操作執行。
當一個變數為Modified時,這個緩存必須監聽所有別的緩存對於該變數對應主存的讀請求,一旦監聽到就必須將這個變數寫入主存。這個過程可以通過強制讓別的緩存等待的方法來完成。當完成了對主存的寫入,狀態變為Shared。但同樣可以直接通知別的緩存這個變數的值,而不寫入主存。
當處於Shared狀態時,必須監聽所有的rfo廣播,一旦收到就讓緩存中的變數無效。
Modified和Exclusive狀態是精確的,當有緩存行處於這個狀態就表明,這個變數是這個緩存獨有的。而Shared狀態時不精確的,當別的緩存丟棄了這個Shared狀態的緩存行,那麼可能只存在一個緩存行狀態為Shared但它不會變為Exclusive。丟棄Shared狀態行不會引起別的緩存的注意。
使用Exclusive可以帶來性能上的提升,因為修改Exclusive不需要通知別的緩存,而修改Shared狀態的緩存行需要告訴別的緩存,並使這些緩存行無效,這是耗時的。(這也是EMSI與MSI協議的區別)
MESI簡單直接的實現存在著兩個性能問題。1.當向一個Invalid的緩存行寫入時,需要從別的緩存獲取值,這是很耗時的。2.需要將別的緩存行的該值設置為Invalid這也是耗時的。為了解決這兩個問題,我們引入了存儲緩沖區和無效化隊列。
當向一個無效的緩存行寫入時會用到儲存緩沖區。因為這個寫操作最終一定會被執行,因此CPU發送讀無效消息(讓別的緩存中的該緩存行無效)並且將要寫入的值放到存儲緩存區中,當這個需要的緩存行寫入緩存時,存儲緩存區中存儲的值將被執行寫入。
存儲緩存區存在帶來的後果是,當一個CPU進行寫操作,值不會立即寫入緩存中。因此,無論何時CPU讀取緩存中的值時,都需要先掃描自己的存儲緩沖區,確保緩沖區中是否還有未寫入的值。值得注意的時不同CPU之間存儲緩沖區時不可見的。
當CPU收到無效請求時,它會將這寫無效請求放入無效化隊列中。放入隊列中的請求會被迅速執行但不是立即執行。所以CPU可以忽略它的緩存塊是無效的。CPU不能掃描它的無效隊列,這是和存儲緩沖區的區別。
可見存儲緩沖區帶來的是寫不同步,而無效化隊列則帶來讀不同步,為了解決這些不同步,我們需要內存屏障。寫屏障會刷新我們的存儲緩沖區,確保裡面所有的寫都會被執行到這個CPU的cache上,而讀屏障可以保證所有無效化隊列里的任務都被執行,確保別的CPU的寫對自己可見。
⑥ CPU多級緩存架構
1、基本概念
1.1、匯流排
前端匯流排(FSB)就是負責將CPU連接到內存的一座橋,前端匯流排頻率則直接影響CPU與內存數據交換速度,如果FSB頻率越高,說明這座橋越寬,可以同時通過的車輛越多,這樣CPU處理的速度就更快。目前PC機上CPU前端匯流排頻率有533MHz、800MHz、1066MHz、1333MHz、1600MHz等幾種,前端匯流排頻率越高,CPU與內存之間的數據傳輸量越大。
前端匯流排——Front Side Bus(FSB),是將CPU連接到北橋晶元的匯流排。選購主板和CPU時,要注意兩者搭配問題,一般來說,前端匯流排是由CPU決定的,如果主板不支持CPU所需要的前端匯流排,系統就無法工作。
1.2、頻率與降頻
只支持1333內存頻率的cpu和主板配1600內存條就會降頻。核心數跟ddr2和ddr3沒關系,核心數是cpu本身的性質,cpu是四核的就是四核的,是雙核的就是雙核的。如果cpu只支持1333,而主板支持1600,那也會降頻;cpu支持1600而主板只支持1333那不僅內存會降頻,而且發揮不出cpu全部性能。
另外如果是較新的主板cpu,已經採用新的qpi匯流排,而不是以前的fsb匯流排。以前的fsb匯流排一般是匯流排為多少就支持多高的內存頻率。而qpi匯流排的cpu集成了內存控制器,5.0gt/s的cpu可能只支持1333內存頻率,但是匯流排帶寬相當於1333內存的內存帶寬的兩倍,這時候,組成1333雙通道,內存速度就會翻倍,相當於2666的內存頻率。
1.3、cache line
Cache Line可以簡單的理解為CPU Cache中的最小緩存單位。目前主流的CPU Cache的Cache Line大小都是64Bytes。假設我們有一個512位元組的一級緩存,那麼按照64B的緩存單位大小來算,這個一級緩存所能存放的緩存個數就是512/64 = 8個。
2、CPU多級緩存架構
級別越小的緩存,越接近CPU, 意味著速度越快且容量越少。
3、多核CPU多級緩存一致性協議MESI
為了解決這個問題,晶元設計者制定了一個規則。當一個 CPU 修改高速緩存行中的位元組時,計算機中的其它 CPU 會被通知,它們的高速緩存將視為無效。於是,在上面的情況下, CPU2 發現自己的高速緩存中數據已無效, CPU1 將立即把自己的數據寫回 RAM ,然後 CPU2 重新讀取該數據。 可以看出,高速緩存行在多處理器上會導致一些不利。
多核CPU的情況下有多個一級緩存,如何保證緩存內部數據的一致,不讓系統數據混亂。這里就引出了一個一致性的協議MESI。
MESI 是指4中狀態的首字母。每個Cache line有4個狀態,可用2個bit表示,它們分別是:
注意: 對於M和E狀態而言總是精確的,他們在和該緩存行的真正狀態是一致的,而S狀態可能是非一致的。如果一個緩存將處於S狀態的緩存行作廢了,而另一個緩存實際上可能已經獨享了該緩存行,但是該緩存卻不會將該緩存行升遷為E狀態,這是因為其它緩存不會廣播他們作廢掉該緩存行的通知,同樣由於緩存並沒有保存該緩存行的的數量,因此(即使有這種通知)也沒有辦法確定自己是否已經獨享了該緩存行。
從上面的意義看來E狀態是一種投機性的優化:如果一個CPU想修改一個處於S狀態的緩存行,匯流排事務需要將所有該緩存行的變成invalid狀態,而修改E狀態的緩存不需要使用匯流排事務。
3.2、MESI狀態轉換
1.觸發事件
觸發事件描述本地讀取(Local read)本地cache讀取本地cache數據本地寫入(Local write)本地cache寫入本地cache數據遠端讀取(Remote read)其他cache讀取本地cache數據遠端寫入(Remote write)其他cache寫入本地cache數據
2.cache分類:
前提:所有的cache共同緩存了主內存中的某一條數據。
本地cache:指當前cpu的cache。
觸發cache:觸發讀寫事件的cache。
其他cache:指既除了以上兩種之外的cache。
注意:本地的事件觸發 本地cache和觸發cache為相同。
下圖示意了,當一個cache line的調整的狀態的時候,另外一個cache line 需要調整的狀態。
3.3、多核緩存協同操作
假設有三個CPU A、B、C,對應三個緩存分別是cache a、b、 c。在主內存中定義了x的引用值為0。
單核讀取
那麼執行流程是:
CPU A發出了一條指令,從主內存中讀取x。
從主內存通過bus讀取到緩存中(遠端讀取Remote read),這是該Cache line修改為E狀態(獨享).
雙核讀取
那麼執行流程是:
CPU A發出了一條指令,從主內存中讀取x。
CPU A從主內存通過bus讀取到 cache a中並將該cache line 設置為E狀態。
CPU B發出了一條指令,從主內存中讀取x。
CPU B試圖從主內存中讀取x時,CPU A檢測到了地址沖突。這時CPU A對相關數據做出響應。此時x 存儲於cache a和cache b中,x在chche a和cache b中都被設置為S狀態(共享)。
修改數據
那麼執行流程是:
CPU A 計算完成後發指令需要修改x.
CPU A 將x設置為M狀態(修改)並通知緩存了x的CPU B, CPU B將本地cache b中的x設置為I狀態(無效)
CPU A 對x進行賦值。
同步數據
那麼執行流程是:
CPU B 發出了要讀取x的指令。
CPU B 通知CPU A,CPU A將修改後的數據同步到主內存時cache a 修改為E(獨享)
CPU A同步CPU B的x,將cache a和同步後cache b中的x設置為S狀態(共享)。
MESI優化和他們引入的問題
緩存的一致性消息傳遞是要時間的,這就使其切換時會產生延遲。當一個緩存被切換狀態時其他緩存收到消息完成各自的切換並且發出回應消息這么一長串的時間中CPU都會等待所有緩存響應完成。可能出現的阻塞都會導致各種各樣的性能問題和穩定性問題。
CPU切換狀態阻塞解決-存儲緩存(Store Bufferes)
比如你需要修改本地緩存中的一條信息,那麼你必須將I(無效)狀態通知到其他擁有該緩存數據的CPU緩存中,並且等待確認。等待確認的過程會阻塞處理器,這會降低處理器的性能。應為這個等待遠遠比一個指令的執行時間長的多。
Store Bufferes
為了避免這種CPU運算能力的浪費,Store Bufferes被引入使用。處理器把它想要寫入到主存的值寫到緩存,然後繼續去處理其他事情。當所有失效確認(Invalidate Acknowledge)都接收到時,數據才會最終被提交。 這么做有兩個風險
Store Bufferes的風險 第一、就是處理器會嘗試從存儲緩存(Store buffer)中讀取值,但它還沒有進行提交。這個的解決方案稱為Store Forwarding,它使得載入的時候,如果存儲緩存中存在,則進行返回。 第二、保存什麼時候會完成,這個並沒有任何保證。
試想一下開始執行時,CPU A保存著finished在E(獨享)狀態,而value並沒有保存在它的緩存中。(例如,Invalid)。在這種情況下,value會比finished更遲地拋棄存儲緩存。完全有可能CPU B讀取finished的值為true,而value的值不等於10。
即isFinsh的賦值在value賦值之前。
這種在可識別的行為中發生的變化稱為重排序(reordings)。注意,這不意味著你的指令的位置被惡意(或者好意)地更改。
它只是意味著其他的CPU會讀到跟程序中寫入的順序不一樣的結果。
3.4、硬體內存模型
執行失效也不是一個簡單的操作,它需要處理器去處理。另外,存儲緩存(Store Buffers)並不是無窮大的,所以處理器有時需要等待失效確認的返回。這兩個操作都會使得性能大幅降低。為了應付這種情況,引入了失效隊列。它們的約定如下:
原文連接
⑦ 救救我,感激不盡,若能挺過這一關,做牛做馬都願意
熔點在Reichart Thermover熱階段放大獲得的。使用Pye Unicam SP- 光譜儀,用溴化鉀光碟記錄紅外光譜。C和H的元素則使用Heraeus CHN - O型快速儀分別完成。質譜記錄採用Finnigan Matt 型質譜儀,在電離勢為70e下操作。'H和13C核磁共振譜在.94和75.43兆赫分別錄得,使用arian 兆赫儀器以CDC13作為溶劑和MeSi(伊利諾斯協定?)作為內部存儲標准。31P 核磁共振譜是使用相同的儀器以CDCl31和加入外部磷酸(D20的85%)在21.42兆赫下測定的。工作中使用的試劑和溶劑是由Fluka(布克斯,瑞士)獲得的。
屬於專業解釋,你要自己理解部分:
第一句,好像句子不全或者Microscope有誤。 Reichart Thermover是德文或者俄文標志的生產廠的加熱儀器,但是也有一種德國產的化學品中出現。
保留所有外文儀器名稱,因為是非英文,德文?
Me$i解釋為Illinois Protocol緩存和內存一致性的協議,
來世?這些就過時了,沒人再為它煩惱了。
⑧ 緩存一致性協議
鎖緩存行有一套協議叫做 緩存一致性協議 。緩存一致性協議有MSI、MESI、MOSI、Synapse、Firefly以及DragonProtocol等等。
MESI分別代表緩存行數據的4中狀態,通過對這四種狀態的切換,來達到對緩存數據進行管理的目的
假設有三個CPU-A、B、C,對應三個緩存分別是cache-a、b、c。在主內存中定義了x的引用值0
單核讀取
MESI優化和引入的問題:各CPU緩存行的狀態是通過消息傳遞來進行的。如果CPU0要對一個在緩存中共享的變數進行寫入,首先需要發送一個失效的消息給到其他緩存了該數據的CPU,並且要等到他們的確認回執。CPU0在這段時間內都會一直處於阻塞狀態,會導致各種各樣的性能問題和穩定性問題。
為了避免阻塞帶來的資源浪費,在CPU中引入了Store Buffer。
CPU在寫入共享數據時,直接把數據寫入到Store Buffer中,同時發送Invalidate消息,然後繼續去處理其他指令。當收到其他所有CPU發送了Invalidate Acknowledge消息時,再將Store Buffer中的數據存儲到Cache Line中,最後再從Cache Line同步到主內存。