自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

CPU 緩存一致性問題深度解析

系統(tǒng)
本文將從最基本的總線嗅探技術(shù)入手,逐步深入探討幾種主流的緩存一致性協(xié)議,特別是 MESI 協(xié)議。

在現(xiàn)代多核處理器系統(tǒng)中,數(shù)據(jù)的一致性和訪問效率是確保高性能計算的關(guān)鍵因素之一。隨著技術(shù)的發(fā)展和應(yīng)用需求的增長,傳統(tǒng)的單核處理架構(gòu)已經(jīng)無法滿足日益復(fù)雜的計算任務(wù)要求。因此,多核乃至多處理器系統(tǒng)的出現(xiàn)成為必然趨勢。然而,在這樣的并行計算環(huán)境中,如何保證各個核心之間的數(shù)據(jù)同步與一致成為了新的挑戰(zhàn)。

緩存一致性問題是多核系統(tǒng)中最為核心的問題之一。當(dāng)多個處理器核心共享同一塊內(nèi)存區(qū)域時,每個核心都可能擁有該內(nèi)存區(qū)域的副本。如果一個核心修改了其緩存中的數(shù)據(jù),其他核心必須能夠及時感知這一變化,以保持?jǐn)?shù)據(jù)的一致性。為了解決這個問題,各種緩存一致性協(xié)議應(yīng)運(yùn)而生。

本文將從最基本的總線嗅探技術(shù)入手,逐步深入探討幾種主流的緩存一致性協(xié)議,特別是MESI協(xié)議。我們將詳細(xì)介紹這些協(xié)議的工作原理、優(yōu)缺點(diǎn)以及對系統(tǒng)性能的影響。希望通過本文的講解,讀者能夠?qū)彺嬉恢滦詥栴}有一個全面的理解,并掌握解決這一問題的有效方法。

一、詳解CPU體系結(jié)構(gòu)和數(shù)據(jù)讀寫機(jī)制

1.CPU Cache Line是什么

每個CPU都會有自己的二級緩存,其中一級緩存分為數(shù)據(jù)緩存和指令緩存,這些緩存的數(shù)據(jù)都是從內(nèi)存中讀取的,而且每次都會加載一個cache line,而CPU Cache Line的物理結(jié)構(gòu)大體如下圖所示:

關(guān)于cache line的大小可以使用命令鍵入如下指令進(jìn)行查看:

cat /sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size

以筆者的服務(wù)器為例,可以看到對應(yīng)的輸出結(jié)果為64:

同時對應(yīng)的我們給出CPU緩存與內(nèi)存的體系結(jié)構(gòu)圖,其中按照數(shù)值減小訪問速度越快,不同CPU核心都有獨(dú)立的二級緩存,而三級緩存則是共享緩沖區(qū),與物理內(nèi)存空間直接打交道:

如果開發(fā)者能夠很好的使用緩存技術(shù),那么程序的性能就會很高,具體可以參照筆者之前寫的這篇文章

計算機(jī)組成原理-基于計組CPU的基礎(chǔ)知識進(jìn)行代碼調(diào)優(yōu):https://blog.csdn.net/shark_chili3007/article/details/123038653

2.CPU Cache和內(nèi)存同步技術(shù)

(1) 寫直達(dá)(Write Through)技術(shù)

寫直達(dá)技術(shù)解決cache和內(nèi)存同步問題的方式很簡單,例如CPU1要操作變量i,先看看cache中有沒有變量i,若有則直接操作cache中的值,然后立刻寫回內(nèi)存。 若變量i不在cache中,那么CPU就回去內(nèi)存中加載這個變量到cache中進(jìn)行操作,然后立刻寫回內(nèi)存中。 這樣做的好處就是實(shí)現(xiàn)簡單,缺點(diǎn)也很明顯,因?yàn)槊看味家獙⑿薷牡臄?shù)據(jù)立刻寫回內(nèi)存,這其中的寫入開銷對于需要高速運(yùn)轉(zhuǎn)的CPU是一種災(zāi)難:

(2) 回寫技術(shù)(Write Back)

Write Back即一種延遲寫技術(shù),為了避免上一種操作頻繁寫入內(nèi)存的資源開銷而提出的一種方案,它的工作原理是將數(shù)據(jù)加載到CPU cache并修改但并不寫入內(nèi)存,僅僅是將數(shù)據(jù)標(biāo)記為dirty,由此減少寫入內(nèi)存的次數(shù),如果沒有發(fā)生緩存置換,這些數(shù)據(jù)就不會被寫入內(nèi)存中。

舉個例子,CPU cache加載data1到緩存中,并進(jìn)行數(shù)次修改操作,隨后cpu cache發(fā)生data10不在緩存中需要從內(nèi)存中加載,又因?yàn)閏pu cache空間不足,此時觸發(fā)緩存置換算法便將最近最少使用且是dirty的數(shù)據(jù)寫到內(nèi)存中,并將data10加載到cpu cache里:

可以看出這種寫法如果出現(xiàn)在毫秒級的斷電場景可能存在數(shù)據(jù)丟失問題,又因?yàn)檠舆t寫的原因,對應(yīng)的數(shù)據(jù)加載在讀未命中的情況下存在兩次操作:

  • 將需要置換的數(shù)據(jù)寫入內(nèi)存。
  • 將需要加載的數(shù)據(jù)拉到cpu cache。

這里我們也補(bǔ)充一下幾種比較常見的緩存置換算法:

  • Belady異常(Belady’s Anomaly)
  • 最近最少使用(Least Recently Used Algorithm)
  • 先進(jìn)先出(FIFO)
  • 后進(jìn)先出(LIFO)

二、詳解CPU緩存一致性問題

1.多核心緩存修改問題

當(dāng)一臺計算機(jī)由多核CPU構(gòu)成的時候,每個CPU都從內(nèi)存里加載相同的變量i(初值為0)進(jìn)行累加操作,我們試想這種情況:

  • CPU-0加載內(nèi)存變量i值為0。
  • CPU-0自增為1準(zhǔn)備寫回內(nèi)存。
  • CPU-1加載內(nèi)存變量i值為0。
  • CPU-1自增為1準(zhǔn)備寫回內(nèi)存。 兩次自增得到結(jié)果1,這就是經(jīng)典的緩存一致性問題:

而解決這個問題我們只要攻破以下兩點(diǎn)問題即可:

  • 寫傳播問題:即當(dāng)前Cache中修改的值要讓其他CPU知道
  • 事務(wù)串行化:例如CPU1先將變量i改為100,CPU2再將基于當(dāng)前變量i的值乘2。我們必須保證變量i先加100,再乘2。

2.總線嗅探(Bus Snooping)

總線嗅探是解決寫傳播的解決方案,舉個例子,當(dāng)CPU1更新Cache中變量i的值時,就會通知其他核心變量i已被修改,當(dāng)其他CPU發(fā)現(xiàn)自己Cache中也有這個值的時候就會將CPU1中cache的結(jié)果更新到自己的cache中。 這種方式缺點(diǎn)很明顯,CPU必須無時不刻監(jiān)聽變化,而且出現(xiàn)變化的數(shù)據(jù)自己還不一定有,這樣的作法增加了總線的壓力:

而且也不能保證事務(wù)串行化,如下圖,CPU-0加載了變量修改了值通知其他CPU這個值有變化了。 而CPU-1也改了i的值,按照正常的邏輯CPU-2、CPU-3的值應(yīng)該是先變?yōu)?00在變?yōu)?00。 但是CPU-3先收到CPU-2的通知先改為200再收到CPU-0的通知變?yōu)?00,這就導(dǎo)致的數(shù)據(jù)不一致的問題,即事務(wù)串行化失敗:

3.MESI協(xié)議如何解決上述問題

MESI是總線嗅探的改良版,他很好的解決了總線的帶寬壓力,以及很好的解決了數(shù)據(jù)一致性問題。 在介紹MESI之前,我們必須了解以下MESI是什么。

  • M(Modified,已修改),MESI第一個字母M,代表著CPU當(dāng)前L1 cache中某個變量i的狀態(tài)被修改了,而且這個數(shù)據(jù)在其他核心中都沒有。
  • E(Exclusive,獨(dú)占),說白了就是CPUA將數(shù)據(jù)加載自己的L1 cache時,其他核心的cache中并沒有這個數(shù)據(jù),所以CPUA將這個數(shù)據(jù)加載到自己的cache時標(biāo)記為E。
  • (S:Shared,共享):說明CPUA在加載這個數(shù)據(jù)時,其他CPU已經(jīng)加載過這個數(shù)據(jù)了,這時CPUA就會從其他CPU中拿到這個數(shù)據(jù)并加載到L1 cache中,并且所有擁有這個值的CPU都會將cache中的這個值標(biāo)記為S。
  • (I:Invalidated,已失效):當(dāng)CPUA修改了L1 cache中的變量i時,發(fā)現(xiàn)這個值是S即共享的數(shù)據(jù),那么就需要通知其他核心這個數(shù)據(jù)被改了,其他CPU都需要將cache中的這個值標(biāo)為I,后面要操作的時,必須拿到最新的數(shù)據(jù)在進(jìn)行操作。

好了介紹完這幾個狀態(tài)之后,我們不妨用一個例子過一下這個流程:

  • CPU-0要加載變量i,發(fā)現(xiàn)變量i不在cache中,于是去內(nèi)存中加載數(shù)據(jù),此時通過總線發(fā)個消息給其他核心,其他核心的cache中并沒有這條數(shù)據(jù),所以這個變量的cache中的狀態(tài)為E(獨(dú)占)。
  • CPU-1也加載這個數(shù)據(jù)了,在總線上發(fā)了個消息,發(fā)現(xiàn)CPU-0有這個數(shù)據(jù)且并沒有修改或者失效的標(biāo)志,于是他們一起將這個變量i狀態(tài)設(shè)置為S(共享)
  • CPU-0要改變量i值了,發(fā)消息給其他核心,其他核心收到消息將自己的變量i設(shè)置為I(無效),CPU-0改完后將數(shù)據(jù)設(shè)置為M(已修改)
  • CPU-0又要改變量i的值了,而且看到變量i的狀態(tài)為M(已修改),說明這個值是最新的數(shù)據(jù),所以不發(fā)消息給其他核心了,直接更新即可。
  • CPU-1要加載變量i,發(fā)現(xiàn)狀態(tài)為I,于是CPU-0將值寫回內(nèi)存,此時狀態(tài)為E,然后CPU-1讀取這個值,大家狀態(tài)都變?yōu)镾共享。
  • CPU-0要加載新的變量i了,而且變量x要使用的cache空間正是變量i的,所以CPU-0將值寫回內(nèi)存中,這時候內(nèi)存和最新數(shù)據(jù)同步了。

三、小結(jié)

自此,我們從多核CPU體系結(jié)構(gòu)所引發(fā)緩存一致性問題為入手,再從總線嗅探到MESI協(xié)議深度講解了緩存一致性問題的解決方案,希望對你有幫助。

責(zé)任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關(guān)推薦

2024-04-11 13:45:14

Redis數(shù)據(jù)庫緩存

2022-09-06 15:30:20

緩存一致性

2020-09-04 06:32:08

緩存數(shù)據(jù)庫接口

2023-04-13 08:15:47

Redis緩存一致性

2019-02-13 11:04:42

系統(tǒng)緩存軟件

2022-08-11 07:55:05

數(shù)據(jù)庫Mysql

2016-11-29 09:00:19

分布式數(shù)據(jù)一致性CAS

2021-09-08 11:03:13

緩存數(shù)據(jù)庫性能

2022-12-14 08:23:30

2024-11-07 22:57:30

2023-08-14 08:10:33

CPU緩存RFO

2019-03-27 13:56:39

緩存雪崩穿透

2020-10-26 19:25:23

CPU緩存Cache

2022-09-16 09:46:42

緩存數(shù)據(jù)庫

2021-06-30 21:13:49

CPUCache數(shù)據(jù)

2025-03-24 10:17:01

2012-09-24 09:35:42

分布式系統(tǒng)

2020-05-12 10:43:22

Redis緩存數(shù)據(jù)庫

2020-06-01 22:09:48

緩存緩存同步緩存誤用

2020-09-22 08:07:50

緩存數(shù)據(jù)一致性
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號