那曲檬骨新材料有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

CPU緩存知識科普

sakobpqhz6 ? 來源:IC學習 ? 2023-07-17 12:26 ? 次閱讀

好久沒有寫一些微觀方面的文章了,今天寫一篇關于CPU Cache相關的文章,這篇文章比較長,主要分成這么幾個部分:基礎知識、緩存的命中、緩存的一致性和延伸閱讀。其中會講述一些多核 CPU 的系統架構以及其原理。這篇文章我會盡量地寫簡單和通俗易懂一些,主要是講清楚相關的原理和問題,而對于一些細節和延伸閱讀我會在文章最后會給出相關的資源。

因為無論你寫什么樣的代碼都會交給CPU來執行,所以,如果你想寫出性能比較高的代碼,這篇文章中提到的技術還是值得認真學習的。另外,千萬別覺得這些東西沒用,這些東西非常有用,十多年前就是這些知識在性能調優上幫了我的很多大忙,從而跟很多人拉開了差距……

基礎知識

首先,我們都知道現在的CPU多核技術,都會有幾級緩存,老的CPU會有兩級緩存(L1和L2),新的CPU會有三級緩存(L1,L2,L3 ),如下圖所示:

9e82b700-2459-11ee-962d-dac502259ad0.png

其中:

L1緩存分成兩種,一種是指令緩存,一種是數據緩存。L2緩存和L3緩存不分指令和數據。

L1緩存和L2緩存在每一個CPU核中,L3則是所有CPU核心共享的緩存。

L1、L2、L3緩存離CPU越近就越小,速度也越快,離CPU越遠,速度就越慢。

再往后面就是內存,內存的后面就是硬盤。我們來看一些他們的速度:

L1 的存取速度:4 個CPU時鐘周期

L2 的存取速度:11 個CPU時鐘周期

L3 的存取速度:39 個CPU時鐘周期

RAM內存的存取速度:107 個CPU時鐘周期

我們可以看到,L1的速度是RAM的27倍,但是L1/L2的大小基本上也就是KB級別的,L3會是MB級別的。例如:Intel Core i7-8700K ,是一個6核的CPU,每核上的L1是64KB(數據和指令各32KB),L2 是 256K,L3有2MB(我的蘋果電腦是 Intel Core i9-8950HK,和Core i7-8700K的Cache大小一樣)。

我們的數據就從內存向上,先到L3,再到L2,再到L1,最后到寄存器進行CPU計算。為什么會設計成三層?這里有下面幾個方面的考慮:

一個方面是物理速度,如果要更大的容量就需要更多的晶體管,除了芯片的體積會變大,更重要的是大量的晶體管會導致速度下降,因為訪問速度和要訪問的晶體管所在的位置成反比,也就是當信號路徑變長時,通信速度會變慢。這部分是物理問題。

另外一個問題是,多核技術中,數據的狀態需要在多個CPU中進行同步,并且,我們可以看到,cache和RAM的速度差距太大,所以,多級不同尺寸的緩存有利于提高整體的性能。

這個世界永遠是平衡的,一面變得有多光鮮,另一面也會變得有多黑暗。建立這么多級的緩存,一定就會引入其它的問題,這里有兩個比較重要的問題,

一個是比較簡單的緩存的命中率的問題。

另一個是比較復雜的緩存更新的一致性問題。

尤其是第二個問題,在多核技術下,這就很像分布式的系統了,要對多個地方進行更新。

緩存的命中

在說明這兩個問題之前。我們需要了解一個術語 Cache Line。緩存基本上來說就是把后面的數據加載到離自己近的地方,對于CPU來說,它是不會一個字節一個字節的加載的,因為這非常沒有效率,一般來說都是要一塊一塊的加載的,對于這樣的一塊一塊的數據單位,術語叫“Cache Line”,一般來說,一個主流的CPU的Cache Line 是 64 Bytes(也有的CPU用32Bytes和128Bytes),64Bytes也就是16個32位的整型,這就是CPU從內存中撈數據上來的最小數據單位。

比如:Cache Line是最小單位(64Bytes),所以先把Cache分布多個Cache Line,比如:L1有32KB,那么,32KB/64B = 512 個 Cache Line。

一方面,緩存需要把內存里的數據放進來,英文叫 Cache Associativity。Cache的數據放置策略決定了內存中的數據塊會拷貝到CPU Cache中的哪個位置上,因為Cache的大小遠遠小于內存,所以,需要有一種地址關聯的算法,能夠讓內存中的數據可以被映射到Cache中來。這個有點像內存地址從邏輯地址向物理地址映射的方法,但不完全一樣。

基本上來說,我們會有如下的一些方法。

一種方法是,任何一個內存地址的數據可以被緩存在任何一個Cache Line里,這種方法是最靈活的,但是,如果我們要知道一個內存是否存在于Cache中,我們就需要進行O(n)復雜度的Cache遍歷,這是很沒有效率的。

另一種方法,為了降低緩存搜索算法,我們需要使用像Hash Table這樣的數據結構,最簡單的hash table就是做“求模運算”,比如:我們的L1 Cache有512個Cache Line,那么,公式(內存地址 mod 512)* 64就可以直接找到所在的Cache地址的偏移了。但是,這樣的方式需要我們的程序對內存地址的訪問要非常地平均,不然沖突就會非常嚴重。這成了一種非常理想的情況了。

為了避免上述的兩種方案的問題,于是就要容忍一定的hash沖突,也就出現了 N-Way 關聯。也就是把連續的N個Cache Line綁成一組,然后,先找到相關的組,然后再在這個組內找到相關的Cache Line。這叫 Set Associativity。如下圖所示。

9e9ae29e-2459-11ee-962d-dac502259ad0.png

對于 N-Way 組關聯,可能有點不好理解,這里個例子,并多說一些細節(不然后面的代碼你會不能理解),Intel 大多數處理器的L1 Cache都是32KB,8-Way 組相聯,Cache Line 是64 Bytes。這意味著,

32KB的可以分成,32KB / 64 = 512 條 Cache Line。

因為有8 Way,于是會每一Way 有 512 / 8 = 64 條 Cache Line。

于是每一路就有 64 x 64 = 4096 Byts 的內存。

為了方便索引內存地址,

Tag:每條 Cache Line 前都會有一個獨立分配的 24 bits來存的 tag,其就是內存地址的前24bits

Index:內存地址后續的6個bits則是在這一Way的是Cache Line 索引,2^6 = 64 剛好可以索引64條Cache Line

Offset:再往后的6bits用于表示在Cache Line 里的偏移量

如下圖所示:(圖片來自《Cache: a place for concealment and safekeeping》)

當拿到一個內存地址的時候,先拿出中間的 6bits 來,找到是哪組。

9ebd8f56-2459-11ee-962d-dac502259ad0.png

然后,在這一個8組的cache line中,再進行O(n) n=8 的遍歷,主要是要匹配前24bits的tag。如果匹配中了,就算命中,如果沒有匹配到,那就是cache miss,如果是讀操作,就需要進向后面的緩存進行訪問了。L2/L3同樣是這樣的算法。而淘汰算法有兩種,一種是隨機一種是LRU。現在一般都是以LRU的算法(通過增加一個訪問計數器來實現)

9ece9e04-2459-11ee-962d-dac502259ad0.png

這也意味著:

L1 Cache 可映射 36bits 的內存地址,一共 2^36 = 64GB的內存

當CPU要訪問一個內存的時候,通過這個內存中間的6bits 定位是哪個set,通過前 24bits 定位相應的Cache Line。

就像一個hash Table的數據結構一樣,先是O(1)的索引,然后進入沖突搜索。

因為中間的 6bits 決定了一個同一個set,所以,對于一段連續的內存來說,每隔4096的內存會被放在同一個組內,導致緩存沖突。

此外,當有數據沒有命中緩存的時候,CPU就會以最小為Cache Line的單元向內存更新數據。當然,CPU并不一定只是更新64Bytes,因為訪問主存實在是太慢了,所以,一般都會多更新一些。好的CPU會有一些預測的技術,如果找到一種pattern的話,就會預先加載更多的內存,包括指令也可以預加載。這叫 Prefetching 技術 (參看,Wikipedia 的 Cache Prefetching 和紐約州立大學的 Memory Prefetching)。比如,你在for-loop訪問一個連續的數組,你的步長是一個固定的數,內存就可以做到prefetching。(注:指令也是以預加載的方式執行,參看本站的《代碼執行的效率》中的第三個示例)

了解這些細節,會有利于我們知道在什么情況下有可能導致緩存的失效。

緩存的一致性

對于主流的CPU來說,緩存的寫操作基本上是兩種策略(參看本站《緩存更新的套路》),

一種是Write Back,寫操作只寫在cache上,然后再flush到內存上。

一種是Write Through,寫操作同時寫到cache和內存上。

為了提高寫操作的性能,一般來說,主流的CPU(如:Intel Core i7/i9)采用的是Write Back的策略,因為直接寫內存實在是太慢了。

好了,現在問題來了,如果有一個數據 x 在 CPU 第0核的緩存上被更新了,那么其它CPU核上對于這個數據 x 的值也要被更新,這就是緩存一致性的問題。(當然,對于我們上層的程序我們不用關心CPU多個核的緩存是怎么同步的,這對上層的代碼來說都是透明的)

一般來說,在CPU硬件上,會有兩種方法來解決這個問題。

Directory 協議。這種方法的典型實現是要設計一個集中式控制器,它是主存儲器控制器的一部分。其中有一個目錄存儲在主存儲器中,其中包含有關各種本地緩存內容的全局狀態信息。當單個CPU Cache 發出讀寫請求時,這個集中式控制器會檢查并發出必要的命令,以在主存和CPU Cache之間或在CPU Cache自身之間進行數據同步和傳輸。

Snoopy 協議。這種協議更像是一種數據通知的總線型的技術。CPU Cache通過這個協議可以識別其它Cache上的數據狀態。如果有數據共享的話,可以通過廣播機制將共享數據的狀態通知給其它CPU Cache。這個協議要求每個CPU Cache 都可以“窺探”數據事件的通知并做出相應的反應。如下圖所示,有一個Snoopy Bus的總線。

9efa1070-2459-11ee-962d-dac502259ad0.png

因為Directory協議是一個中心式的,會有性能瓶頸,而且會增加整體設計的復雜度。而Snoopy協議更像是微服務+消息通訊,所以,現在基本都是使用Snoopy的總線的設計。

這里,我想多寫一些細節,因為這種微觀的東西,讓人不自然地就會跟分布式系統關聯起來,在分布式系統中我們一般用Paxos/Raft這樣的分布式一致性的算法。而在CPU的微觀世界里,則不必使用這樣的算法,原因是因為CPU的多個核的硬件不必考慮網絡會斷、會延遲的問題。所以,CPU的多核心緩存間的同步的核心就是要管理好數據的狀態就好了。

這里介紹幾個狀態協議,先從最簡單的開始,MESI協議,這個協議跟那個著名的足球運動員梅西沒什么關系,其主要表示緩存數據有四個狀態:Modified(已修改), Exclusive(獨占的),Shared(共享的),Invalid(無效的)。

這些狀態的狀態機如下所示(有點復雜,你可以先不看,這個圖就是想告訴你狀態控制有多復雜):

9f0f7fe6-2459-11ee-962d-dac502259ad0.png

下面是個示例(如果你想看一下動畫演示的話,這里有一個網頁(MESI Interactive Animations),你可以進行交互操作,這個動畫演示中使用的Write Through算法):

9f2adaca-2459-11ee-962d-dac502259ad0.png

MESI 這種協議在數據更新后,會標記其它共享的CPU緩存的數據拷貝為Invalid狀態,然后當其它CPU再次read的時候,就會出現 cache miss 的問題,此時再從內存中更新數據。從內存中更新數據意味著20倍速度的降低。我們能不能直接從我隔壁的CPU緩存中更新?是的,這就可以增加很多速度了,但是狀態控制也就變麻煩了。還需要多來一個狀態:Owner(宿主),用于標記,我是更新數據的源。于是,出現了 MOESI 協議

MOESI協議的狀態機和演示示例我就不貼了(有興趣可以上Berkeley上看看相關的課件),我們只需要理解MOESI協議允許 CPU Cache 間同步數據,于是也降低了對內存的操作,性能是非常大的提升,但是控制邏輯也非常復雜。

順便說一下,與 MOESI 協議類似的一個協議是MESIF,其中的 F 是 Forward,同樣是把更新過的數據轉發給別的 CPU Cache 但是,MOESI 中的 Owner 狀態 和MESIF 中的 Forward 狀態有一個非常大的不一樣——Owner狀態下的數據是dirty的,還沒有寫回內存,Forward狀態下的數據是clean的,可以丟棄而不用另行通知。

需要說明的是,AMD用MOESI,Intel用MESIF。所以,F 狀態主要是針對 CPU L3 Cache 設計的(前面我們說過,L3是所有CPU核心共享的)。(相關的比較可以參看StackOverlow上這個問題的答案)

總之,這個CPU Cache的調優技術不是什么新鮮的東西,只要Google就能找到有很多很多文章……

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 芯片
    +關注

    關注

    456

    文章

    51192

    瀏覽量

    427301
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10905

    瀏覽量

    213030
  • 緩存
    +關注

    關注

    1

    文章

    241

    瀏覽量

    26758
  • 多核技術
    +關注

    關注

    0

    文章

    5

    瀏覽量

    7165

原文標題:CPU緩存知識

文章出處:【微信號:IC學習,微信公眾號:IC學習】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    CPU、GPU和內存知識科普

    本文內容包括CPU、內存和GPU知識,本期重點更新GPU和CPU部分知識。比如:GPU更新包括架構演進,最新產品A100、選型策略、架構分析、散熱和規格分類等。
    的頭像 發表于 11-13 11:47 ?2036次閱讀
    <b class='flag-5'>CPU</b>、GPU和內存<b class='flag-5'>知識</b><b class='flag-5'>科普</b>

    CPU一級緩存

    CPU一級緩存              CPU緩存(Cache
    發表于 12-24 10:21 ?463次閱讀

    CPU二級緩存容量

    CPU二級緩存容量            CPU緩存(Cache Memory)是位
    發表于 12-24 10:22 ?541次閱讀

    什么是CPU一級緩存/二級緩存

    什么是CPU一級緩存/二級緩存?  即L1 Cache。集成在CPU內部中,用于CPU在處理數據過程中數據的暫時保存。由于
    發表于 02-04 10:43 ?1191次閱讀

    什么是CPU緩存/前端總線(FSB)頻率

    什么是CPU緩存/前端總線(FSB)頻率  緩存   緩存大小也是CPU的重要指標之一,而且
    發表于 02-04 11:22 ?1451次閱讀

    CPU緩存對性能的影響

      說到CPU,不得不說的就是CPU緩存,目前CPU緩存已經成了衡量CPU性能的一個必要指標,
    發表于 11-13 17:58 ?2530次閱讀

    CPU緩存是什么意思_CPU緩存有什么作用

    由于處理器是核心硬件,相信我們在選擇處理器的時候都會去關心處理器參數方面,而在處理器核心參數中,我們經常會看到緩存(Cache)這個參數,那么CPU緩存有什么作用呢?下面小編科普一下
    發表于 05-19 09:24 ?7792次閱讀

    緩存如何工作,如何設計CPU緩存

    20世紀80年代,CPU性能有了顯著提升,但這受到板載內存訪問速度緩慢增長的阻礙。隨著這種差異的惡化,工程師們發現了一種通過新的設計技術緩存來解決問題的方法。本文將幫助你進一步了解什么是緩存,它如何工作以及如何設計
    的頭像 發表于 11-19 17:23 ?2796次閱讀

    CPU緩存的作用及原理有哪些

    CPU緩存是位于CPU與內存之間的臨時存儲器,它的容量比內存小很多,但交換速度比內存要快很多。 CPU緩存分為三類:一級
    的頭像 發表于 08-27 15:58 ?1.1w次閱讀

    關于CPU緩存的作用

    CPU沒有存儲功能,那么緩存到底是干什么的?CPU緩存是用于減少處理器訪問內存所需平均時間的部件,作用類似于CPU內部的內存。
    的頭像 發表于 03-30 10:58 ?4604次閱讀
    關于<b class='flag-5'>CPU</b><b class='flag-5'>緩存</b>的作用

    CPU緩存設計的原則及工作原理

    本文將研究 CPU 緩存設計的原則,包括局部性、邏輯組織和啟發式管理。
    的頭像 發表于 04-28 17:19 ?3610次閱讀
    <b class='flag-5'>CPU</b><b class='flag-5'>緩存</b>設計的原則及工作原理

    cpu緩存的作用及原理是什么

    CPU高速緩存集成于CPU的內部,其是CPU可以高效運行的成分之一,本文圍繞下面三個話題來講解CPU緩存
    發表于 08-21 12:17 ?2421次閱讀
    <b class='flag-5'>cpu</b><b class='flag-5'>緩存</b>的作用及原理是什么

    電氣基本知識科普

    電氣基本知識科普
    的頭像 發表于 09-09 10:23 ?6182次閱讀
    電氣基本<b class='flag-5'>知識</b><b class='flag-5'>科普</b>

    CPU緩存那些事兒

    CPU Cache 在讀取內存數據時,每次不會只讀一個字或一個字節,而是一塊塊地讀取,這每一小塊數據也叫CPU 緩存行(CPU Cache Line)。這也是對局部性原理的運用,當一個
    的頭像 發表于 09-10 10:57 ?727次閱讀
    <b class='flag-5'>CPU</b><b class='flag-5'>緩存</b>那些事兒

    什么是CPU緩存?它有哪些作用?

    CPU緩存(Cache Memory)是計算機系統中一個至關重要的組成部分,它位于CPU與內存之間,作為兩者之間的臨時存儲器。CPU緩存的主
    的頭像 發表于 08-22 14:54 ?3754次閱讀
    樱桃木百家乐官网桌| 皇冠赌球| 大发888 bet娱乐场下载| 凯斯线上娱乐| 百家乐官网娱乐城有几家| 上海百家乐官网赌博| 百家乐官网网上真钱赌场娱乐网规则| 百家乐官网平注法亏损| 百家乐五湖四海娱乐城| 做生意门口怎么摆放| 百家乐赌博经历| 新全讯网3344666| 桑植县| 百家乐官网赢钱公式1| 百家乐官网娱乐城新闻| 百家乐官网号公| 百家乐规律和方法| 最新娱乐城注册送体验金| 百家乐官网投注技巧球讯网| 澳门百家乐官网赌场文| 山西百家乐用品| 互联星空棋牌中心| 百家乐官网庄闲比率| 百家乐官网五铺的缆是什么意思| 百家乐路子技巧| 皇冠正网| 百家乐官网娱乐平台会员注册| 澳门百家乐图形| 爱赢娱乐城| 三公百家乐官网玩法| 娱乐城百家乐送白菜| 视频棋牌游戏| 蓝盾百家乐官网洗码| 百家乐赌注| 百家乐优博u2bet| 棋牌类单机游戏下载| 澳门百家乐官网赌场网址| 百家乐解密软件| 鸿运国际娱乐| 丽景湾百家乐官网的玩法技巧和规则| 澳门百家乐论坛及玩法|