CPU高速緩存行與內存關係 及併發MESI 協議

先來一個總體圖html

一.前端

大體關係: CPU Cache --> 前端總線 FSB (下圖中的Bus) --> Memory 內存java

CPU 爲了更快的執行代碼。因而當從內存中讀取數據時,並非只讀本身想要的部分。而是讀取足夠的字節來填入高速緩存行。根據不一樣的 CPU ,高速緩存行大小不一樣。如 X86 是 32BYTES ,而 ALPHA 是 64BYTES 。而且始終在第 32 個字節或第 64 個字節處對齊。這樣,當 CPU 訪問相鄰的數據時,就沒必要每次都從內存中讀取,提升了速度。 由於訪問內存要比訪問高速緩存用的時間多得多。設計模式

下面一張圖能夠看出各級緩存之間的響應時間差距,以及內存到底有多慢!數組

   (2)總線概念緩存

前端總線(FSB)就是負責將CPU鏈接到內存的一座橋,前端總線頻率則直接影響CPU與內存數據交換速度,若是FSB頻率越高,說明這座橋越寬,能夠同時經過的車輛越多,這樣CPU處理的速度就更快。目前PC機上CPU前端總線頻率有533MHz、800MHz、1066MHz、1333MHz、1600MHz等幾種,前端總線頻率越高,CPU與內存之間的數據傳輸量越大。
前端總線——Front Side Bus(FSB),是將CPU鏈接到北橋芯片的總線。選購主板和CPU時,要注意二者搭配問題,通常來講,前端總線是由CPU決定的,若是主板不支持CPU所須要的前端總線,系統就沒法工做安全

  (3) 頻率與降頻概念數據結構

    只支持1333內存頻率的cpu和主板配1600內存條就會降頻。核心數跟ddr2和ddr3不要緊,核心數是cpu自己的性質,cpu是四核的就是四核的,是雙核的就是雙核的。
    若是隻cpu支持1333,而主板支持1600,那也會降頻;cpu支持1600而主板只支持1333那不只內存會降頻,並且發揮不出cpu所有性能。
     另外若是是較新的主板cpu,已經採用新的qpi總線,而不是之前的fsb總線。
    之前的fsb總線通常是總線爲多少就支持多高的內存頻率。而qpi總線的cpu集成了內存控制器,5.0
    gt/s的cpu可能只支持1333內存頻率,可是總線帶寬至關於1333內存的內存帶寬的兩倍,這時候,組成1333雙通道,內存速度就會翻倍,至關於2666的內存頻率。架構

二. CPU Cache和Cache Line

什麼是Cache Line

Cache Line能夠簡單的理解爲CPU Cache中的最小緩存單位。目前主流的CPU Cache的Cache Line大小都是64Bytes。假設咱們有一個512字節的一級緩存,那麼按照64B的緩存單位大小來算,這個一級緩存所能存放的緩存個數就是512/64 = 8個。具體參見下圖:app

爲了更好的瞭解Cache Line,咱們還能夠在本身的電腦上作下面這個有趣的實驗。

下面這段C代碼,會從命令行接收一個參數做爲數組的大小建立一個數量爲N的int數組。並依次循環的從這個數組中進行數組內容訪問,循環10億次。最終輸出數組總大小和對應總執行時間。

#include "stdio.h"
#include <stdlib.h>
#include <sys/time.h>
 
long  timediff(clock_t  t1, clock_t  t2) {
    long  elapsed;
    elapsed = ((double)t2 - t1) / CLOCKS_PER_SEC * 1000;
    return  elapsed;
}
 
int  main(int  argc, char  *argv[])
#*******
{
 
    int  array_size=atoi(argv[1]);
    int  repeat_times = 1000000000;
    long  array[array_size];
    for(int  i=0; i<array_size; i++){
        array[i] = 0;
    }
    int  j=0;
    int  k=0;
    int  c=0;
    clock_t  start=clock();
    while(j++<repeat_times){
        if(k==array_size){
            k=0;
        }
        c = array[k++];
    }
    clock_t  end =clock();
    printf("%lu\n", timediff(start,end));
    return  0;
}

 

  若是咱們把這些數據作成折線圖後就會發現:總執行時間在數組大小超過64Bytes時有較爲明顯的拐點(固然,因爲博主是在本身的Mac筆記本上測試的,會受到不少其餘程序的干擾,所以會有波動)。緣由是當數組小於64Bytes時數組極有可能落在一條Cache Line內,而一個元素的訪問就會使得整條Cache Line被填充,於是值得後面的若干個元素受益於緩存帶來的加速。而當數組大於64Bytes時,必然至少須要兩條Cache Line,繼而在循環訪問時會出現兩次Cache Line的填充,因爲緩存填充的時間遠高於數據訪問的響應時間,所以多一次緩存填充對於總執行的影響會被放大,最終獲得下圖的結果:

咱們來看下面這個C語言中經常使用的循環優化例子
下面兩段代碼中,第一段代碼在C語言中老是比第二段代碼的執行速度要快。具體的緣由相信你仔細閱讀了Cache Line的介紹後就很容易理解了。

for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) { int num; arr[i][j] = num; } }
for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) { int num; arr[j][i] = num; } }

 

三. 下面看CPU Cache與Memory關係圖

上述左圖是最簡單的高速緩存的圖示,數據的讀取和存儲都通過高速緩存,CPU核心和高速緩存之間有一條特殊的快速通道,在這個簡化的圖示上,主存(main memory)與高速緩存(cache)都連在系統總線上。這條總線同時還用於其餘組件之間的通訊。在高速緩存出現後不久,系統變得更加複雜,高速緩存與主存之間的速度差別被拉大,直到加入了另外一級的緩存(因爲加大一級緩存的作法從經濟上考慮是行不通的,因此有了二級緩存甚至三級緩存)。新加入的這些緩存比第一緩存更大可是更慢。

 

多核發達的年代。狀況就不能那麼簡單了。試想下面這樣一個狀況。

一、      CPU1 讀取了一個字節,以及它和它相鄰的字節被讀入 CPU1 的高速緩存。

二、      CPU2 作了上面一樣的工做。這樣 CPU1 , CPU2 的高速緩存擁有一樣的數據。

三、      CPU1 修改了那個字節,被修改後,那個字節被放回 CPU1 的高速緩存行。可是該信息並無被寫入 RAM 。

四、      CPU2 訪問該字節,但因爲 CPU1 並未將數據寫入 RAM ,致使了數據不一樣步。

 

爲了解決這個問題,芯片設計者制定了一個規則。當一個 CPU 修改高速緩存行中的字節時,計算機中的其它 CPU 會被通知,它們的高速緩存將視爲無效。因而,在上面的狀況下, CPU2 發現本身的高速緩存中數據已無效, CPU1 將當即把本身的數據寫回 RAM ,而後 CPU2 從新讀取該數據。 能夠看出,高速緩存行在多處理器上會致使一些不利。

 

四.  多核CPU多級緩存一致性協議MESI

多核CPU的狀況下有多個一級緩存,如何保證緩存內部數據的一致,不讓系統數據混亂。這裏就引出了一個一致性的協議MESI。

MESI協議緩存狀態

MESI 是指4中狀態的首字母。每一個Cache line有4個狀態,可用2個bit表示,它們分別是:

緩存行(Cache line):緩存存儲數據的單元。

狀態 描述 監放任務
M 修改 (Modified) 該Cache line有效,數據被修改了,和內存中的數據不一致,數據只存在於本Cache中。 緩存行必須時刻監聽全部試圖讀該緩存行相對就主存的操做,這種操做必須在緩存將該緩存行寫回主存並將狀態變成S(共享)狀態以前被延遲執行。
E 獨享、互斥 (Exclusive) 該Cache line有效,數據和內存中的數據一致,數據只存在於本Cache中。 緩存行也必須監聽其它緩存讀主存中該緩存行的操做,一旦有這種操做,該緩存行須要變成S(共享)狀態。
S 共享 (Shared) 該Cache line有效,數據和內存中的數據一致,數據存在於不少Cache中。 緩存行也必須監聽其它緩存使該緩存行無效或者獨享該緩存行的請求,並將該緩存行變成無效(Invalid)。
I 無效 (Invalid) 該Cache line無效。

注意:
對於M和E狀態而言老是精確的,他們在和該緩存行的真正狀態是一致的,而S狀態多是非一致的。若是一個緩存將處於S狀態的緩存行做廢了,而另外一個緩存實際上可能已經獨享了該緩存行,可是該緩存卻不會將該緩存行升遷爲E狀態,這是由於其它緩存不會廣播他們做廢掉該緩存行的通知,一樣因爲緩存並無保存該緩存行的copy的數量,所以(即便有這種通知)也沒有辦法肯定本身是否已經獨享了該緩存行。

從上面的意義看來E狀態是一種投機性的優化:若是一個CPU想修改一個處於S狀態的緩存行,總線事務須要將全部該緩存行的copy變成invalid狀態,而修改E狀態的緩存不須要使用總線事務。

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爲相同。

上圖的切換解釋:

狀態 觸發本地讀取 觸發本地寫入 觸發遠端讀取 觸發遠端寫入
M狀態(修改) 本地cache:M
觸發cache:M
其餘cache:I
本地cache:M
觸發cache:M
其餘cache:I
本地cache:M→E→S
觸發cache:I→S
其餘cache:I→S
同步主內存後修改成E獨享,同步觸發、其餘cache後本地、觸發、其餘cache修改成S共享
本地cache:M→E→S→I
觸發cache:I→S→E→M
其餘cache:I→S→I
同步和讀取同樣,同步完成後觸發cache改成M,本地、其餘cache改成I
E狀態(獨享) 本地cache:E
觸發cache:E
其餘cache:I
本地cache:E→M
觸發cache:E→M
其餘cache:I
本地cache變動爲M,其餘cache狀態應當是I(無效)
本地cache:E→S
觸發cache:I→S
其餘cache:I→S
當其餘cache要讀取該數據時,其餘、觸發、本地cache都被設置爲S(共享)
本地cache:E→S→I
觸發cache:I→S→E→M
其餘cache:I→S→I
當觸發cache修改本地cache獨享數據時時,將本地、觸發、其餘cache修改成S共享.而後觸發cache修改成獨享,其餘、本地cache修改成I(無效),觸發cache再修改成M
S狀態(共享) 本地cache:S
觸發cache:S
其餘cache:S
本地cache:S→E→M
觸發cache:S→E→M
其餘cache:S→I
當本地cache修改時,將本地cache修改成E,其餘cache修改成I,而後再將本地cache爲M狀態
本地cache:S
觸發cache:S
其餘cache:S
本地cache:S→I
觸發cache:S→E→M
其餘cache:S→I
當觸發cache要修改本地共享數據時,觸發cache修改成E(獨享),本地、其餘cache修改成I(無效),觸發cache再次修改成M(修改)
I狀態(無效) 本地cache:I→S或者I→E
觸發cache:I→S或者I →E
其餘cache:E、M、I→S、I
本地、觸發cache將從I無效修改成S共享或者E獨享,其餘cache將從E、M、I 變爲S或者I
本地cache:I→S→E→M
觸發cache:I→S→E→M
其餘cache:M、E、S→S→I
既然是本cache是I,其餘cache操做與它無關 既然是本cache是I,其餘cache操做與它無關

下圖示意了,當一個cache line的調整的狀態的時候,另一個cache line 須要調整的狀態。

  M E S I
M × × ×
E × × ×
S × ×
I

舉個栗子來講:

假設cache 1 中有一個變量x = 0的cache line 處於S狀態(共享)。
那麼其餘擁有x變量的cache 二、cache 3等x的cache line調整爲S狀態(共享)或者調整爲 I 狀態(無效)。

多核緩存協同操做

假設有三個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的風險

第1、就是處理器會嘗試從存儲緩存(Store buffer)中讀取值,但它尚未進行提交。這個的解決方案稱爲Store Forwarding,它使得加載的時候,若是存儲緩存中存在,則進行返回。
第2、保存何時會完成,這個並無任何保證。

value = 3void exeToCPUA(){ value = 10; isFinsh = true; } void exeToCPUB(){ if(isFinsh){ //value必定等於10?!
    assert value == 10; } }

 

 

試想一下開始執行時,CPU A保存着finished在E(獨享)狀態,而value並無保存在它的緩存中。(例如,Invalid)。在這種狀況下,value會比finished更遲地拋棄存儲緩存。徹底有可能CPU B讀取finished的值爲true,而value的值不等於10。

即isFinsh的賦值在value賦值以前。

這種在可識別的行爲中發生的變化稱爲重排序(reordings)。注意,這不意味着你的指令的位置被惡意(或者好意)地更改。

它只是意味着其餘的CPU會讀到跟程序中寫入的順序不同的結果。

順便提一下NIO的設計和Store Bufferes的設計是很是相像的。

硬件內存模型

執行失效也不是一個簡單的操做,它須要處理器去處理。另外,存儲緩存(Store Buffers)並非無窮大的,因此處理器有時須要等待失效確認的返回。這兩個操做都會使得性能大幅下降。爲了應付這種狀況,引入了失效隊列。它們的約定以下:

  • 對於全部的收到的Invalidate請求,Invalidate Acknowlege消息必須馬上發送
  • Invalidate並不真正執行,而是被放在一個特殊的隊列中,在方便的時候纔會去執行。
  • 處理器不會發送任何消息給所處理的緩存條目,直到它處理Invalidate。

即使是這樣處理器已然不知道何時優化是容許的,而何時並不容許。
乾脆處理器將這個任務丟給了寫代碼的人。這就是內存屏障(Memory Barriers)。

寫屏障 Store Memory Barrier(a.k.a. ST, SMB, smp_wmb)是一條告訴處理器在執行這以後的指令以前,應用全部已經在存儲緩存(store buffer)中的保存的指令。

讀屏障Load Memory Barrier (a.k.a. LD, RMB, smp_rmb)是一條告訴處理器在執行任何的加載前,先應用全部已經在失效隊列中的失效操做的指令。

void executedOnCpu0() { value = 10; //在更新數據以前必須將全部存儲緩存(store buffer)中的指令執行完畢。
 storeMemoryBarrier(); finished = true; } void executedOnCpu1() { while(!finished); //在讀取以前將全部失效隊列中關於該數據的指令執行完畢。
 loadMemoryBarrier(); assert value == 10; }

 

如今確實安全了。完美無暇!

從上面的狀況能夠看出,在設計數據結構的時候,應該儘可能將只讀數據與讀寫數據分開,並具儘可能將同一時間訪問的數據組合在一塊兒。這樣 CPU 能一次將須要的數據讀入。

如:

Struct __a { Int id; // 不易變
 Int factor;// 易變
 Char name[64];// 不易變
 Int value;// 易變
 } ; 這樣的數據結構就很不利。 在 X86 下,能夠試着修改和調整它 Struct __a { Int id; // 不易變
 Char name[64];// 不易變
 Char __Align[32sizeof(int)+sizeof(name)*sizeof(name[0])%32] Int factor;// 易變
 Int value;// 易變
 Char __Align2[322* sizeof(int)%32] } ;

 

五.  CPU Cache 是如何存放數據的

你會怎麼設計Cache的存放規則

咱們先來嘗試回答一下那麼這個問題:

假設咱們有一塊4MB的區域用於緩存,每一個緩存對象的惟一標識是它所在的物理內存地址。每一個緩存對象大小是64Bytes,全部能夠被緩存對象的大小總和(即物理內存總大小)爲4GB。那麼咱們該如何設計這個緩存?

若是你和博主同樣是一個大學沒有好好學習基礎/數字電路的人的話,會以爲最靠譜的的一種方式就是:Hash表。把Cache設計成一個Hash數組。內存地址的Hash值做爲數組的Index,緩存對象的值做爲數組的Value。每次存取時,都把地址作一次Hash而後找到Cache中對應的位置操做便可。
這樣的設計方式在高等語言中很常見,也顯然很高效。由於Hash值得計算雖然耗時(10000個CPU Cycle左右),可是相比程序中其餘操做(上百萬的CPU Cycle)來講能夠忽略不計。而對於CPU Cache來講,原本其設計目標就是在幾十CPU Cycle內獲取到數據。若是訪問效率是百萬Cycle這個等級的話,還不如到Memory直接獲取數據。固然,更重要的緣由是在硬件上要實現Memory Address Hash的功能在成本上是很是高的。

爲何Cache不能作成Fully Associative

Fully Associative 字面意思是全關聯。在CPU Cache中的含義是:若是在一個Cache集內,任何一個內存地址的數據能夠被緩存在任何一個Cache Line裏,那麼咱們成這個cache是Fully Associative。從定義中咱們能夠得出這樣的結論:給到一個內存地址,要知道他是否存在於Cache中,須要遍歷全部Cache Line並比較緩存內容的內存地址。而Cache的本意就是爲了在儘量少得CPU Cycle內取到數據。那麼想要設計一個快速的Fully Associative的Cache幾乎是不可能的。

爲何Cache不能作成Direct Mapped

和Fully Associative徹底相反,使用Direct Mapped模式的Cache給定一個內存地址,就惟一肯定了一條Cache Line。設計複雜度低且速度快。那麼爲何Cache不使用這種模式呢?讓咱們來想象這麼一種狀況:一個擁有1M L2 Cache的32位CPU,每條Cache Line的大小爲64Bytes。那麼整個L2Cache被劃爲了1M/64=16384條Cache Line。咱們爲每條Cache Line從0開始編上號。同時32位CPU所能管理的內存地址範圍是2^32=4G,那麼Direct Mapped模式下,內存也被劃爲4G/16384=256K的小份。也就是說每256K的內存地址共享一條Cache Line。

可是,這種模式下每條Cache Line的使用率若是要作到接近100%,就須要操做系統對於內存的分配和訪問在地址上也是近乎平均的。而與咱們的意願相反,爲了減小內存碎片和實現便捷,操做系統更多的是連續集中的使用內存。這樣會出現的狀況就是0-1000號這樣的低編號Cache Line因爲內存常常被分配並使用,而16000號以上的Cache Line因爲內存鮮有進程訪問,幾乎一直處於空閒狀態。這種狀況下,原本就寶貴的1M二級CPU緩存,使用率也許50%都沒法達到。

什麼是N-Way Set Associative

爲了不以上兩種設計模式的缺陷,N-Way Set Associative緩存就出現了。他的原理是把一個緩存按照N個Cache Line做爲一組(set),緩存按組劃爲等分。這樣一個64位系統的內存地址在4MB二級緩存中就劃成了三個部分(見下圖),低位6個bit表示在Cache Line中的偏移量,中間12bit表示Cache組號(set index),剩餘的高位46bit就是內存地址的惟一id。這樣的設計相較前兩種設計有如下兩點好處:

  • 給定一個內存地址能夠惟一對應一個set,對於set中只需遍歷16個元素就能夠肯定對象是否在緩存中(Full Associative中比較次數隨內存大小線性增長)
  • 每2^18(256K)*64=16M的連續熱點數據纔會致使一個set內的conflict(Direct Mapped中512K的連續熱點數據就會出現conflict)

爲何N-Way Set Associative的Set段是從低位而不是高位開始的

下面是一段從How Misaligning Data Can Increase Performance 12x by Reducing Cache Misses摘錄的解釋:

The vast majority of accesses are close together, so moving the set index bits upwards would cause more conflict misses. You might be able to get away with a hash function that isn’t simply the least significant bits, but most proposed schemes hurt about as much as they help while adding extra complexity.

因爲內存的訪問一般是大片連續的,或者是由於在同一程序中而致使地址接近的(即這些內存地址的高位都是同樣的)。因此若是把內存地址的高位做爲set index的話,那麼短期的大量內存訪問都會由於set index相同而落在同一個set index中,從而致使cache conflicts使得L2, L3 Cache的命中率低下,影響程序的總體執行效率。

瞭解N-Way Set Associative的存儲模式對咱們有什麼幫助

瞭解N-Way Set的概念後,咱們不可貴出如下結論:2^(6Bits <Cache Line Offset> + 12Bits <Set Index>) = 2^18 = 512K。即在連續的內存地址中每512K都會出現一個處於同一個Cache Set中的緩存對象。也就是說這些對象都會爭搶一個僅有16個空位的緩存池(16-Way Set)。而若是咱們在程序中又使用了所謂優化神器的「內存對齊」的時候,這種爭搶就會愈加增多。效率上的損失也會變得很是明顯。具體的實際測試咱們能夠參考: How Misaligning Data Can Increase Performance 12x by Reducing Cache Misses 一文。

這裏咱們引用一張Gallery of Processor Cache Effects 中的測試結果圖,來解釋下內存對齊在極端狀況下帶來的性能損失。

該圖其實是咱們上文中第一個測試的一個變種。縱軸表示了測試對象數組的大小。橫軸表示了每次數組元素訪問之間的index間隔。而圖中的顏色表示了響應時間的長短,藍色越明顯的部分表示響應時間越長。從這個圖咱們能夠獲得不少結論。固然這裏咱們只對內存帶來的性能損失感興趣。有興趣的讀者也能夠閱讀原文分析理解其餘從圖中能夠獲得的結論。

從圖中咱們不難看出圖中每1024個步進,即每1024*4即4096Bytes,都有一條特別明顯的藍色豎線。也就是說,只要咱們按照4K的步進去訪問內存(內存根據4K對齊),不管熱點數據多大它的實際效率都是很是低的!按照咱們上文的分析,若是4KB的內存對齊,那麼一個80MB的數組就含有20480個能夠被訪問到的數組元素;而對於一個每512K就會有set衝突的16Way二級緩存,總共有512K/20480=25個元素要去爭搶16個空位。那麼緩存命中率只有64%,天然效率也就低了。

想要知道更多關於內存地址對齊在目前的這種CPU-Cache的架構下會出現的問題能夠詳細閱讀如下兩篇文章:

  • How Misaligning Data Can Increase Performance 12x by Reducing Cache Misses
  • Gallery of Processor Cache Effects

 

Cache淘汰策略

在文章的最後咱們順帶提一下CPU Cache的淘汰策略。常見的淘汰策略主要有LRU和Random兩種。一般意義下LRU對於Cache的命中率會比Random更好,因此CPU Cache的淘汰策略選擇的是LRU。固然也有些實驗顯示在Cache Size較大的時候Random策略會有更高的命中率

 

參考來源:

1. CPU高速緩存行   https://blog.csdn.net/boyuejiang/article/details/8908335

2. 關於CPU Cache和Cache Line  https://blog.csdn.net/midion9/article/details/49487919

3. CPU緩存一致性協議MESI   https://www.cnblogs.com/yanlong300/p/8986041.html

相關文章
相關標籤/搜索