深度学习arm cache系列--一篇就够了
引流關鍵詞:緩存,高速緩存,cache, CCI,CMN,CCI-550,CCI-500,DSU,SCU,L1,L2,L3,system cache, Non-cacheable,Cacheable, non-shareable,inner-shareable,outer-shareable, optee、ATF、TF-A、Trustzone、optee3.14、MMU、VMSA、cache、TLB、arm、armv8、armv9、TEE、安全、內存管理、頁表…
快速鏈接:
.
👉👉👉 個人博客筆記導讀目錄(全部) 👈👈👈
目錄
- 1. cache的基本概念介紹
- 1.1、為什么要用cache?
- 1.2、為什么要學習cache呢?
- 1.2.1、軟件中維護內存一致性 – invalid cache
- 1.2.2、軟件中維護內存一致性 – flush cache
- 1.3、怎么去刷cache呢?
- 1.3.1、cache一致性指令介紹
- 1.3.2、cache一致性指令的使用示例
- 1.3.3、 操作系統中軟件維護cache一致性的API
- 1.4、總結
- 2. cache的基本概念原理掃盲
- 2.1、cache是多級相連的
- 2.2、cache一般是和MMU結合在一起使用的
- 2.3、`bit-LITTLE`架構 和 `DynamIQ`架構 的cache是有區別的
- 2.3.1 `bit-LITTLE`架構的cache
- 2.3.2 `DynamIQ`架構架構的cache
- 2.4、L1/L2/L3 cache的大小
- 2.5、cache的組織形式(index, way, set)
- 2.6、cache的種類(VIVT,PIPT,VIPT)
- 2.7、cache的分配策略(alocation,write-through, write-back)
- 2.8、架構中定義的cache的范圍(inner, outer)
- 2.9、架構中內存的類型
- 3. cache的查詢原理
- 3.1. cache的查詢原理
- 3.2. cache的查詢示例
- 4. 多核多cluster多系統之間緩存一致性概述
- 4.1. 質疑
- 4.2. 怎樣去維護多核多系統緩存的一致性
- 4.3. bit.LITTLE架構 和 DynamIQ架構 的系統中的緩存一致性
- 4.4. MESI、MOESI 的介紹
- 4.5. 總結
- 5. 多級cache之間的替換策略
- 5.1、DynamIQ架構中L1 cache的替換策略(以cortex-A710為例)
- 5.2、core cache的替換策略(以cortex-A710為例)
- 5.2.1、L1 data cache 遵從MESI協議
- 5.2.2、L1 instruction cache 沒有遵從MESI協議
- 5.2.3、MESI協議的介紹
- 5.3、cluster cache 之間的替換策略
- 5.4、總結
- 5.5 參考
- 6. A53 cache的架構解讀
- 6.1. A53使用經典的 `bit-LITTLE`架構
- 6.2. A53的cache配置
- 6.3. cache的層級結構:
- 6.4. L2 memory System系統介紹
- 6.5. 多cluster之間的緩存一致性
- 6.6. CCI的介紹(以CCI-550為例)
- 6.7. 經典示例框圖
1. cache的基本概念介紹
1.1、為什么要用cache?
ARM 架構剛開始開發時,處理器的時鐘速度和內存的訪問速度大致相似。今天的處理器內核要復雜得多,并且時鐘頻率可以快幾個數量級。然而,外部總線和存儲設備的頻率并沒有達到同樣的程度。可以實現可以與內核以相同速度運行的小片上 SRAM塊,但與標準 DRAM 塊相比,這種 RAM 非常昂貴,標準 DRAM 塊的容量可能高出數千倍。在許多基于 ARM 處理器的系統中,訪問外部存儲器需要數十甚至數百個內核周期。
高速緩存是位于核心和主內存之間的小而快速的內存塊。它在主內存中保存項目的副本。對高速緩沖存儲器的訪問比對主存儲器的訪問快得多。每當內核讀取或寫入特定地址時,它首先會在緩存中查找。如果它在高速緩存中找到地址,它就使用高速緩存中的數據,而不是執行對主存儲器的訪問。通過減少緩慢的外部存儲器訪問時間的影響,這顯著提高了系統的潛在性能。通過避免驅動外部信號的需要,它還降低了系統的功耗
1.2、為什么要學習cache呢?
cache和我們軟件工程師有啥關系?其實在很多時候,都沒有太大的關系,在很多時候也無需去理解cache的原理。但事實就是事實,不管你理解還是不理解,你都是一直在用的。做為一名底層的軟件開發者,在有些時候,你不得不去主動刷新cache,即軟件中維護內存一致性 。
那么一般什么時候需要主動刷cache呢(軟件中維護內存一致性) ? 基本就是當有不同的Master來訪問相同的內存的時候。如下便是幾個小示例。
1.2.1、軟件中維護內存一致性 – invalid cache
1.2.2、軟件中維護內存一致性 – flush cache
1.3、怎么去刷cache呢?
ARM提供了操作cache的指令, 軟件維護操作cache的指令有三類:
- Invalidation:其實就是修改valid bit,讓cache無效,主要用于讀
- Cleaning: 其實就是我們所說的flush cache,這里會將cache數據回寫到內存,并清楚dirty標志
- Zero:將cache中的數據清0, 這里其實是我們所說的clean cache.
什么時候需要軟件維護cache:
(1)、當有其它的Master改變的external memory,如DMA操作
(2)、MMU的enable或disable的整個區間的內存訪問,如REE enable了mmu,TEE disable了mmu.
針對第(2)點,cache怎么和mmu扯上關系了呢?那是因為:
mmu的開啟和關閉,影響了內存的permissions, cache policies
1.3.1、cache一致性指令介紹
因為本節為第一篇,也就是基本的概念介紹。我們很多深入的原理還不明白。所以就不對以下指令做深入的解讀。你只需理解有這么多指令可用于“軟件維護cache的一致性”就好。后續當深入理解了cache的各種策略原理后,再回過頭來看這些指令,相信會有較大的收獲。
以下是對維護cache的一致性指令做出的一個總結
1.3.2、cache一致性指令的使用示例
1.3.3、 操作系統中軟件維護cache一致性的API
在操作系統中,我們只需要調用相關的API即可,也無需牢記以上的維護cache一致性的命令。
比如在Linux Kernel 操作Cache的API如下所示:
linux/arch/arm64/mm/cache.S linux/arch/arm64/include/asm/cacheflush.hvoid __flush_icache_range(unsigned long start, unsigned long end); int invalidate_icache_range(unsigned long start, unsigned long end); void __flush_dcache_area(void *addr, size_t len); void __inval_dcache_area(void *addr, size_t len); void __clean_dcache_area_poc(void *addr, size_t len); void __clean_dcache_area_pop(void *addr, size_t len); void __clean_dcache_area_pou(void *addr, size_t len); long __flush_cache_user_range(unsigned long start, unsigned long end); void sync_icache_aliases(void *kaddr, unsigned long len); void flush_icache_range(unsigned long start, unsigned long end) void __flush_icache_all(void)1.4、總結
小小總結一下,當有其它硬件(如DMA)和CPU訪問同一塊內存時,那么這個時候的操作需要小心,一般也就是記得調用invalid cache和flush cache相關的函數即可
2. cache的基本概念原理掃盲
2.1、cache是多級相連的
cache是多級的,在一個系統中你可能會看到L1、L2、L3, 當然越靠近core就越小,也是越昂貴。
一般來說,對于bit.LITTLE架構中,在L1是core中,L1又分為L1 data cache和 L1 Instruction cache, L2 cache在cluster中,L3則在BUS總線上。
2.2、cache一般是和MMU結合在一起使用的
很多時候cache都是和MMU一起使用的(即同時開啟或同時關閉),因為MMU頁表的entry的屬性中控制著內存權限和cache緩存策略等
在ARM架構中,L1 cache都是VIPT的,也就是當有一個虛擬地址送進來,MMU在開始進行地址翻譯的時候,Virtual Index就可以去L1 cache中查詢了,MMU查詢和L1 cache的index查詢是同時進行的。如果L1 Miss了,則再去查詢L2,L2還找不到則再去查詢L3。 注意在arm架構中,僅僅L1是VIPT,L2和L3都是PIPT。
2.3、bit-LITTLE架構 和 DynamIQ架構 的cache是有區別的
2.3.1 bit-LITTLE架構的cache
以下是一張比較早期的經典的bit-LITTLE的架構圖
在bit-LITTLE的架構中,L1是在core中的,是core私有的;L2是在cluster中的,對cluster中的core是共享的;L3則對所有cluster共享。bit-LITTLE的架構的一個cache層級關系圖如下所示:
2.3.2 DynamIQ架構架構的cache
隨著時代的發展科技的進步,除了了DynamIQ架構后,整個系統的system memory架構也在悄然無息的發生了變化。剛開始的架構如下所示:L1/L2在core中,L3在DSU中,DSU對外是ACE接口,結合CCI 來維護多cluster之間的緩存一致性。
但是在后來,隨著CHI的越來越成熟,又變成了:L1/L2在core中,L3在DSU中,DSU對外是CHI接口,結合CMN來維護多cluster之間的緩存一致性。
但是不管怎么說,在dynamIQ的架構中,L1和L2都在core中的,都是core私有的;L3則是在cluster中的,對cluster中的core是共享的;如有L3或system cache,則是所有cluster共享。dynamIQ的架構的一個cache層級關系圖如下所示:
2.4、L1/L2/L3 cache的大小
可以參考ARM文檔,其實每一個core的cache大小都是固定的或可配置的。
2.5、cache的組織形式(index, way, set)
cache的組織形式有:
- 全相連
- 直接相連
- 多路組相連(如4路組相連)
在一個core中一個架構中一個SOC中,所有cache的組織形式并不是都一樣的。即使L1 D-cache和L1 I-cache的組織形式,也都可能不是一樣的的。 具體的組織形式是怎樣的,需要查詢你的core trm手冊。
因為有了多路組相連這個cache,所以也就有了這些術語概念:
- index : 用白話理解,其實就是在一塊cache中,一行一行的編號(事實是沒有編號/地址的)
- Set :用index查詢到的cache line可能是多個,這些index值一樣的cacheline稱之為一個set
- way:用白話來說,將cache分成了多個塊(多路),每一塊是一個way
- cache TAG :查詢到了一行cache后,cachelne由 TAG + DATA組成
- cache Data :查詢到了一行cache后,cachelne由 TAG + DATA組成
- cache Line 和 entry 是一個概念
2.6、cache的種類(VIVT,PIPT,VIPT)
cache一般是有如下種類;
- PIPT
- VIVT
- VIPT
在一個core中一個架構中一個SOC中,你所使用的cache是哪種類型的,都是固定的,是軟件改不了的。在ARM架構中,一般L1 cache都是VIPT的,其余的都是PIPT的。
VIPT和PIPT的原理,基本也都是一樣的,只是硬件查詢時稍微有一丁點的區別,在后續講cache查詢時會再次介紹。
那么,你還學什么VIVT?你為什么還要去理解VIVT的原理?你為什么還要去分析cache同名、重名的問題? 這樣的問題,在armv7/armv8/armv9架構中都是不存在的
2.7、cache的分配策略(alocation,write-through, write-back)
-
讀分配(read allocation)
當CPU讀數據時,發生cache缺失,這種情況下都會分配一個cache line緩存從主存讀取的數據。默認情況下,cache都支持讀分配。 -
讀分配(read allocation)寫分配(write allocation)
當CPU寫數據發生cache缺失時,才會考慮寫分配策略。當我們不支持寫分配的情況下,寫指令只會更新主存數據,然后就結束了。當支持寫分配的時候,我們首先從主存中加載數據到cache line中(相當于先做個讀分配動作),然后會更新cache line中的數據。 -
寫直通(write through)
當CPU執行store指令并在cache命中時,我們更新cache中的數據并且更新主存中的數據。cache和主存的數據始終保持一致。 -
讀分配(read allocation)寫回(write back)
當CPU執行store指令并在cache命中時,我們只更新cache中的數據。并且每個cache line中會有一個bit位記錄數據是否被修改過,稱之為dirty bit(翻翻前面的圖片,cache line旁邊有一個D就是dirty bit)。我們會將dirty bit置位。主存中的數據只會在cache line被替換或者顯示的clean操作時更新。因此,主存中的數據可能是未修改的數據,而修改的數據躺在cache中。cache和主存的數據可能不一致
2.8、架構中定義的cache的范圍(inner, outer)
對于cacheable屬性,inner和outer描述的是cache的定義或分類。比如把L1/L1看做是inner,把L3看做是outer
通常,內部集成的cache屬于inner cache,外部總線AMBA上的cache屬于outer cache。例如:
- 對于big.LITTLE架構(A53為例)中,L1/L2屬于inner cache,如果SOC上掛了L3的話,則其屬于outer cache
- 對于DynamIQ架構(A76為例)中,L1/L2/L3屬于inner cache,如果SOC上掛了System cache(或其它名稱)的話,則其屬于outer cache
然后我們可以對每類cache進行單獨是屬性配置,例如:
- 配置 inner Non-cacheable 、配置 inner Write-Through Cacheable 、配置 inner Write-back Cacheable
- 配置 outer Non-cacheable 、配置 outer Write-Through Cacheable 、配置 outer Write-back Cacheable
對于shareable屬性,inner和outer描述的是cache的范圍。比如inner是指L1/L2范圍內的cache,outer是指L1/L2/L3范圍內的cache
2.9、架構中內存的類型
在arm架構中,將物理內存分成了device和normal兩種類型
而是每種的內存下(device和normal)又分出了多種屬性。ARM提供一個MAIR寄存器, 將一個64位的寄存器分成8個attr屬性域,每個attr屬性域有8個比特,可配置成不同的內存屬性。
也就是說,在一個arm core,最多支持8中物理內存類型。
而我們在MMU使用的頁表的entry中的屬性位中,BIT[4:2]占3個比特,表示index,其實就是指向MAIR寄存器中的attr。
也就說說,頁表的每一個entry中,都指向MAIR寄存器中的一個屬性域。也就是頁表的每一個entry都配置了一種內存類型。
3. cache的查詢原理
3.1. cache的查詢原理
高速緩存控制器(cache controller )是負責管理高速緩存內存的硬件塊,其方式對程序來說在很大程度上是不可見的。它自動將代碼或數據從主存寫入緩存。它從core接收讀取和寫入內存請求,并對高速緩存或外部存儲器執行必要的操作。
當它收到來自core的請求時,它必須檢查是否能在緩存中找到所請求的地址。這稱為緩存查找(cache look-up)。它通過將請求的地址位的subset(index)與與緩存中的physical TAG 進行比較來做到這一點。如果存在匹配,稱為命中(hit),并且該行被標記為有效,則使用高速緩存進行讀取或寫入。
當core從特定地址請求指令或數據,但與緩存標簽不匹配或標簽無效時,會導致緩存未命中,請求必須傳遞到內存層次結構的下一層,即 L2緩存或外部存儲器。它還可能導致緩存行填充。緩存行填充會導致將一塊主內存的內容復制到緩存中。同時,請求的數據或指令被流式傳輸到core。這個過程軟件開發人員不能直接看到。在使用數據之前,core不需要等待 linefill 完成。高速緩存控制器通常首先訪問高速緩存行內的關鍵字。例如,如果您執行的加載指令在緩存中未命中并觸發緩存行填充,則內核首先檢索緩存行中包含所請求數據的那部分。這些關鍵數據被提供給core流水線,而緩存硬件和外部總線接口隨后在后臺讀取緩存線的其余部分。
總結一下就是:先使用index去查詢cache,然后再比較TAG,比較TAG之后再檢查valid標志位。
但是這里要注意:TAG包含了不僅僅是物理地址,還有很多其它的東西,如NS比特位等,這些都是在比較TAG的時候完成。
3.2. cache的查詢示例
假設一個4路相連的cache(如cortex-A710),大小64KB, cache line = 64bytes,那么 1 way = 16KB,indexs = 16KB / 64bytes = 256 (注: 0x4000 = 16KB、0x40 = 64 bytes)
0x4000 – index 0
0x4040 – index 1
0x4080 – index 2
…
0x7fc0 – index 255
0x8000 – index 0
0x8040 – index 1
0x8080 – index 2
…
0xbfc0 – index 255
細心的同學可以發現,這里就有了一個很大的問題,你用于cache look-up的index是vaddr[15:6], 如果granue size是4KB,那么vaddr[11:0] = paddrr[11:0] , 但是vaddr[15:12]比特并不等于paddrr[15:12] ,那么你這樣的index查詢的cache有效嗎?會不會發生同名、歧義 ?
其實大可不必擔心,因為對于每個core,L1是VIPT的,其實它們的L1 Cache TAG中,已經規定了physical address[39:12],正好是到BIT12。所以只要TAG比較之后,就不會出現同名和歧義。
4. 多核多cluster多系統之間緩存一致性概述
4.1. 質疑
網上的好多篇博文,一提Cache的多核一致性就必然提到MESI、MOESI ,然后就開始講MESI、MOESI維護性原理?試問一下,您是真的不理解MES嗎?您真的需要學習MESI?你不理解的是架構對吧,而不是學什么鬼協議!
既然您要學了MESI,那么這里也提出幾個問題:
(1)、ARM架構中真的使用MESI了嗎? 或者是哪一級使用了,哪一級沒有使用?
(2)、MESI是一個協議? 是誰來維護的?總得有個硬件實現這個協議吧,是在ARM Core中? CCI-400中?SCU中?DSU中?
(3)、MESI的四種狀態,分別記錄在哪里的?
4.2. 怎樣去維護多核多系統緩存的一致性
有三種機制可以保持一致性:
- 禁用緩存是最簡單的機制,但可能會顯著降低 CPU 性能。為了獲得最高性能,處理器通過管道以高頻率運行,并從提供極低延遲的緩存中運行。緩存多次訪問的數據可顯著提高性能并降低 DRAM 訪問和功耗。將數據標記為“非緩存”可能會影響性能和功耗。
- 軟件管理的一致性是數據共享問題的傳統解決方案。在這里,軟件(通常是設備驅動程序)必須清除或刷新緩存中的臟數據,并使舊數據無效,以便與系統中的其他處理器或主設備共享。這需要處理器周期、總線帶寬和功率。
- 硬件管理的一致性提供了一種簡化軟件的替代方案。使用此解決方案,任何標記為“共享”的緩存數據將始終自動更新。該共享域中的所有處理器和總線主控器看到的值完全相同。
燃鵝,我們在ARM架構中,默認使用的卻是第三種 硬件管理的一致性, 意思就是:做為一名軟件工程師,我們啥也不用管了,有人幫我們干活,雖然如此,但我們還是希望理解下硬件原理。
再講原理之前,我們先補充一個場景:
假設在某一操作系統中運行了一個線程,該線程不停著操作0x4000_0000地址處內存(所以我們當然期望,它總是命中著),由于系統調度,這一次該線程可能跑在cpu0上,下一次也許就跑在cpu1上了,再下一次也許就是cpu4上了(其實這種行為也叫做CPU migration)
或者舉個這樣的場景也行:
在Linux Kernel系統中,定義了一個全局性的變量,然后多個內核線程(多個CPU)都會訪問該變量.
在以上的場景中,都存在一塊內存(如0x4000_0000地址處內存)被不同的ARM CORE來訪問,這樣就會出現了該數據在main-memory、SCU-0的L2 cache、SCU-1的L2 cache、8個Core的L1 cache不一致的情況。
既然出現了數據在內存和不同的cache中的不一致的情況,那么就需要解決這個問題(也叫維護一致性),那么怎么維護的呢,上面也說了“使用 硬件管理的一致性”,下面就以直接寫答案的方式,告訴你硬件是怎樣維護一致性的。
4.3. bit.LITTLE架構 和 DynamIQ架構 的系統中的緩存一致性
我們先看一張老的圖(bit.LITTLE架構的)吧
- core1、core1的cache的一致性,是由SCU-0來維護的(至于這里是不是遵守了MESI協議,答案:YES)
- cluster0、cluster1的cache的一致性,是由于CCI-400來維護的(至于這里是不是遵守了MESI協議,答案:NO)
再看一張比較新的圖(DynamIQ架構的)吧 - core0的cache(含L1/L2)、core1的cache(含L1/L2)的一致性 由DSU-0來維護(至于這里是不是遵守了MESI協議,答案: YES)
- cluster0的 L3 cache、cluster1的 L3 cache、Mali的L2 cache的一致性是由于CCI-550來維護的(至于這里是不是遵守了MESI協議,NO)
4.4. MESI、MOESI 的介紹
注意著僅僅是一個協議 ,它既不是軟件也不是硬件,算上一個標準吧。既然只是一個協議(標準),那總得有硬件來執行維護該協議吧。一般來講,在core cache之間的一致性是要遵從MESI/MOESI協議的,由SCU(或DSU)硬件來執行維護該協議的。在ARM架構中,也并非所有的緩存都遵從MESI/MOESI協議,僅僅只是在一個cluster中的core cache中,才需要遵從MESI/MOESI協議。而對于不同的core,又遵從著不同的協議,具體請查略你的core TRM手冊,上面會說明你的core cache是使用MESI還是MOESI。 接下來我們就來看一下MESI協議部分。
首先是Modified Exclusive Shared Invalid (MESI) 協議中定義了4個狀態:
| Modified (M) | 這行數據有效,數據已被修改,和內存中的數據不一致,數據只存在于該高速緩存中 |
| Exclusive (E) | 這行數據有效,數據和內存中數據一致,數據只存在于該高速緩存中 |
| Shared (S) | 這行數據有效,數據和內存中數據一致,多個高速緩存有這行數據的副本 |
| Invalid (I) | 這行數據無效 |
其次,在ARM的部分的core中,定義了第五種狀態Shared Modified,這種稱之為MOESI協議. 而ARM使用的則是MOESI的變體(啥叫變體,咋變的,變的哪些,文當它沒有說)
然后我們通過數據流圖的方式,觀看下MESI這四種狀態的情況:
MESI狀態之間的切換:
Events:
RH = Read Hit
RMS = Read miss, shared
RME = Read miss, exclusive
WH = Write hit
WM = Write miss
SHR = Snoop hit on read
SHI = Snoop hit on invalidate
LRU = LRU replacement
Bus Transactions:
Push = Write cache line back to memory
Invalidate = Broadcast invalidate
Read = Read cache line from memory
4.5. 總結
- 看完以上信息,我們再次總結一下,我們學習cache一致性,我們最大的困惑或瓶頸是啥,是不理解MESI嗎?應該還是對架構的理解和認知。學習MESI,不如去學習cache硬件基礎、cache TAG、DSU、CCI-550原理吧。
- 多核之間的緩存一致性,由SCU(DSU)硬件來執行維護,使用MESI協議
- 多cluster之間的緩存一致性,由 CCI/CMN 來執行維護,沒有使用MESI協議
5. 多級cache之間的替換策略
思考:
1、L1 cache的替換策略是什么,L2和L3的呢
2、哪些的替換策略是由硬件決定的(定死的,軟件不可更改的),哪些的替換策略是軟件可以配置的?
3、在經典的 DynamIQ架構 中,數據是什么時候存在L1 cache,什么時候存進L2 cache,什么時候又存進L3 cache,以及他們的替換策略是怎樣的? 比如什么時候數據只在L1? 什么時候數據只在L2? 什么時候數據只在L3? 還有一些組合,比如什么時候數組同時在L1和L3,而L2沒有? 這一切的規則是怎樣定義的?
說明:
本文討論經典的DynamIQ的cache架構,忽略 big.LITTLE的cache架構
5.1、DynamIQ架構中L1 cache的替換策略(以cortex-A710為例)
我們先看一下DynamIQ架構中的cache中新增的幾個概念:
- (1) Strictly inclusive: 所有存在L1 cache中的數據,必然也存在L2 cache中
- (2) Weakly inclusive: 當miss的時候,數據會被同時緩存到L1和L2,但在之后,L2中的數據可能會被替換
- (3) Fully exclusive: 當miss的時候,數據只會緩存到L1
其實inclusive/exclusive屬性描述的正是是 L1和L2之間的替換策略,這部分是硬件定死的,軟件不可更改的。
我們再去查閱 ARMV9 cortex-A710 trm手冊,查看該core的cache類型,得知:
- L1 I-cache和L2之間是 weakly inclusive的
- L1 D-cache和L2之間是 strictly inclusive的
也就是說:
- 當發生D-cache發生miss時,數據緩存到L1 D-cache的時候,也會被緩存到L2 Cache中,當L2 Cache被替換時,L1 D-cache也會跟著被替換
- 當發生I-cache發生miss時,數據緩存到L1 I-cache的時候,也會被緩存到L2 Cache中,當L2 Cache被替換時,L1 I- cache不會被替換
再次總結 : L1 和 L2之間的cache的替換策略,I-cache和D-cache可以是不同的策略,每一個core都有每一個core的做法,請查閱你使用core的手冊。
5.2、core cache的替換策略(以cortex-A710為例)
為了能夠將DynamIQ架構和bit.LITTLE架構的cache放在一起介紹,我們將DynamIQ架構中的L1/L2 cache看做成一個單元統稱Core cache,bit.LITTLE架構中的L1 Cache也稱之為core cache.
DynamIQ架構中DSU中的L3 cache稱之為cluster cache,bit.LITTLE架構中SCU中的L2 cache也稱之為cluster cache。
5.2.1、L1 data cache 遵從MESI協議
在L1 data cache TAG中,有記錄MESI相關比特, 然后將一個core內的cache看做是一個整體,core與core之間的緩存一致性,就由DSU執行MESI協議來維護
5.2.2、L1 instruction cache 沒有遵從MESI協議
因為對于Instruction cache來說,都是只讀的,cpu不會改寫I-cache中的數據,所以也就不需要硬件維護多核之間緩存的不一致
5.2.3、MESI協議的介紹
MESI這四種狀態:
MESI狀態之間的切換:
Events:
RH = Read Hit
RMS = Read miss, shared
RME = Read miss, exclusive
WH = Write hit
WM = Write miss
SHR = Snoop hit on read
SHI = Snoop hit on invalidate
LRU = LRU replacement
Bus Transactions:
Push = Write cache line back to memory
Invalidate = Broadcast invalidate
Read = Read cache line from memory
5.3、cluster cache 之間的替換策略
說實話,core cache / cluster cache / 這個名字可能不好,感覺叫private cache 和 share cache也會更好,我也不知道官方一般使用哪個,反正我們能理解其意思即可吧。
那么他們之間的替換策略是怎樣的呢?
我們知道MMU的頁表中的表項中,管理者每一塊內存的屬性,其實就是cache屬性,也就是緩存策略。
其中就有cacheable和shareable、Inner和Outer的概念。如下是針對 DynamIQ 架構做出的總結,注意哦,僅僅是針對 DynamIQ 架構的cache。
-
如果將block的內存屬性配置成Non-cacheable,那么數據就不會被緩存到cache,那么所有observer看到的內存是一致的,也就說此時也相當于Outer Shareable。
其實官方文檔,也有這一句的描述:
在B2.7.2章節 “Data accesses to memory locations are coherent for all observers in the system, and correspondingly are treated as being Outer Shareable” -
如果將block的內存屬性配置成write-through cacheable 或 write-back cacheable,那么數據會被緩存cache中。write-through和write-back是緩存策略。
-
如果將block的內存屬性配置成 non-shareable, 那么core0訪問該內存時,數據緩存的到Core0的L1 D-cache / L2 cache (將L1/L2看做一個整體,直接說數據會緩存到core0的private cache更好),不會緩存到其它cache中。
-
如果將block的內存屬性配置成 inner-shareable, 那么core0訪問該內存時,數據只會緩存到core 0的L1 D-cache / L2 cache和 DSU L3 cache,不會緩存到System Cache中(當然如果有system cache的話 ) , (注意這里MESI協議其作用了)此時core0的cache TAG中的MESI狀態是E, 接著如果這個時候core1也去讀該數據,那么數據也會被緩存core1的L1 D-cache / L2 cache 和DSU0的L3 cache(白字黑字,絕不瞎說,請參見文末的[1] DSU TRM片段), 此時core0和core1的MESI狀態都是S
-
如果將block的內存屬性配置成 outer-shareable, 那么core0訪問該內存時,數據會緩存到core 0的L1 D-cache / L2 cache 、cluster0的DSU L3 cache 、 System Cache中, core0的MESI狀態為E。如果core1再去讀的話,則也會緩存到core1的L1 D-cache / L2 cache,此時core0和core1的MESI都是S。這個時候,如果core7也去讀的話,數據還會被緩存到cluster1的DSU L3 cache. 至于DSU0和DSU1之間的一致性,非MESI維護,具體怎么維護的請看DSU手冊,本文不展開討論。
| non-shareable | 數據不會緩存到cache (對于觀察則而言,又相當于outer-shareable) | core0訪問該內存時,數據緩存的到Core0的L1 D-cache / L2 cache (將L1/L2看做一個整體,直接說數據會緩存到core0的private cache更好),不會緩存到其它cache中 | 同左側 |
| inner-shareable | 數據不會緩存到cache (對于觀察則而言,又相當于outer-shareable) | core0訪問該內存時,數據只會緩存到core 0的L1 D-cache / L2 cache和 DSU L3 cache,不會緩存到System Cache中(當然如果有system cache的話 ) , (注意這里MESI協議其作用了)此時core0的cache TAG中的MESI狀態是E, 接著如果這個時候core1也去讀該數據,那么數據也會被緩存core1的L1 D-cache / L2 cache 和DSU0的L3 cache, 此時core0和core1的MESI狀態都是S | 同左側 |
| outer-shareable | 數據不會緩存到cache (對于觀察則而言,又相當于outer-shareable) | core0訪問該內存時,數據會緩存到core 0的L1 D-cache / L2 cache 、cluster0的DSU L3 cache 、 System Cache中, core0的MESI狀態為E。如果core1再去讀的話,則也會緩存到core1的L1 D-cache / L2 cache,此時core0和core1的MESI都是S 思考:那么此時core7去讀取會怎樣? | 同左側 |
5.4、總結
- dynamIQ 架構中 L1和L2之間的替換策略,是由core的inclusive/exclusive的硬件特性決定的,軟無法更改
- core cache之間的替換策略,是由SCU(或DSU)執行的MESI協議中定義的,軟件也無法更改。
- cluster cache之間的替換策略,是由于MMU頁表中的內存屬性定義的(innor/outer/cacheable/shareable),軟件可以修改
5.5 參考
- [1] DSU TRM片段
6. A53 cache的架構解讀
6.1. A53使用經典的 bit-LITTLE架構
以下是一張比較早期的經典的bit-LITTLE的架構圖
6.2. A53的cache配置
L1 I-Cache
- 可配:8KB, 16KB, 32KB, or 64KB
- cacheline:64bytes
- 2路組相連
- 128-bit的讀L2 memory的接口
L1 D-Cache
- 可配:8KB, 16KB, 32KB, or 64KB
- cacheline:64bytes
- 4路組相連
- 256-bit的寫L2 memory的接口
- 128-bit的讀L2 memory的接口
- 64-bit的讀L1到datapath
- 128-bit的寫datapath到L1
L2 memory System
- 集成了SCU( Snoop Control Unit ),做多可以連接4個core
- SCU內重復拷貝了 L1 Data Cache的TAGs
- L2 memory system對外的接口,可以是ACE 或 CHI,128-bit寬度
L2 cache
- 可配置的: 128KB, 256KB, 512KB, 1MB and 2MB.
- cacheline:64bytes
- Physically indexed and tagged cache(PIPT)
- 16路組相連的結構
L1 data cache TAG
A53的L1 Data cache遵從的是MOESI協議,如下所示在L1 data cache的tag中存有MOESI的標記位
MOESI state
L1 Instruction cache TAG
L1 instruction cache是只讀的,所以也就無需硬件維護的多core之間instruction cache的一致性,所以也就無需組從MOESI協議,以下展示了*L1 Instruction cache的TAG,其中標記為很少,無MESI標記位。
6.3. cache的層級結構:
- L1 cache是private的在core中
- L2 cache是share的在cluster中
6.4. L2 memory System系統介紹
在bit.LITTLE架構中中,在Cluster中,有一個SCU單元,SCU單元主要是執行和維護L1 cache的一致性(MESI協議 或 其變體如MOESI協議)。
在L2 Memory System的中,除了包含L2 cache,也會包含L1 Duplicate tag RAM(這里指的其實是L1 Data Cache Tags)。
6.5. 多cluster之間的緩存一致性
cluster和外界的接口,可以是ACE或CHI(目前常用的是ACE,后面的趨勢可能是CHI)
- 如果使用的是ACE,那么多cluster之間的一致性,依靠CCI + ACE 來維護
- 如果使用的是CHI,那么多cluster之間的一致性,依靠CMN + CHI來維護
6.6. CCI的介紹(以CCI-550為例)
CCI-550 包含一個包容性監聽過濾器(snoop filter),用于記錄存儲在ACE 主緩存。
偵聽過濾器可以在未命中的情況下響應偵聽事務,并偵聽適當的主控只有在命中的情況下。Snoop 過濾器條目通過觀察來自 ACE 主節點的事務來維護以確定何時必須分配和取消分配條目。
偵聽過濾器可以響應多個一致性請求,而無需向所有人廣播ACE 接口。例如,如果地址不在任何緩存中,則監聽過濾器會以未命中和將請求定向到內存。如果地址在處理器緩存中,則請求被視為命中,并且指向在其緩存中包含該地址的 ACE 端口。
6.7. 經典示例框圖
歡迎添加微信、微信群,多多交流
總結
以上是生活随笔為你收集整理的深度学习arm cache系列--一篇就够了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [专栏目录]-ATF/FF-A/spec
- 下一篇: python批量处理jira上的issu