深刻理解緩存cache(1):獲取計算機的cache參數

       存儲器是分層次的,離CPU越近的存儲器,速度越快,每字節的成本越高,同時容量也所以越小。寄存器速度最快,離CPU最近,成本最高,因此個數容量有限,其次是高速緩存(緩存也是分級,有L1,L2等緩存),再次是主存(普通內存),再次是本地磁盤。  
                      



     寄存器的速度最快,能夠在一個時鐘週期內訪問,其次是高速緩存,能夠在幾個時鐘週期內訪問,普通內存能夠在幾十個或幾百個時鐘週期內訪問。

    
          (注 本圖來自Ulrich Drepper大牛的講稿,若有侵權,通知即刪)

    存儲器分級,利用的是局部性原理。咱們能夠以經典的閱讀書籍爲例。我在讀的書,捧在手裏(寄存器),我最近頻繁閱讀的書,放在書桌上(緩存),隨時取來讀。固然書桌上只能放有限幾本書。我更多的書在書架上(內存)。若是書架上沒有的書,就去圖書館(磁盤)。我要讀的書若是手裏沒有,那麼去書桌上找,若是書桌上沒有,去書架上找,若是書架上沒有去圖書館去找。能夠對應寄存器沒有,則從緩存中取,緩存中沒有,則從內存中取到緩存,若是內存中沒有,則先從磁盤讀入內存,再讀入緩存,再讀入寄存器。

    本系列的文章重點介紹緩存cache。瞭解如何獲取cache的參數,瞭解緩存的組織結構,瞭解cache對程序的影響,瞭解如何利用cache提高性能。

    
     本文做爲系列文章的第一篇,講述的如何獲取cache的組成結構和如何獲取cache的參數。

    cache分紅多個組,每一個組分紅多個行,linesize是cache的基本單位,從主存向cache遷移數據都是按照linesize爲單位替換的。好比linesize爲32Byte,那麼遷移必須一次遷移32Byte到cache。 這個linesize比較容易理解,想一想咱們前面書的例子,咱們從書架往書桌搬書必須以書爲單位,確定不能把書撕了以頁爲單位。書就是linesize。固然了現實生活中每本書頁數不一樣,可是同個cache的linesize老是相同的。

    所謂8路組相連( 8-way set associative)的含義是指,每一個組裏面有8個行。
 
    咱們知道,cache的容量要遠遠小於主存,主存和cache確定不是一一對應的,那麼主存中的地址和cache的映射關係是怎樣的呢?

    拿到一個地址,首先是映射到一個組裏面去。如何映射?取內存地址的中間幾位來映射。

    舉例來講,data cache: 32-KB, 8-way set associative, 64-byte line size

    Cache總大小爲32KB,8路組相連(每組有8個line),每一個line的大小linesize爲64Byte,OK,咱們能夠很輕易的算出一共有32K/8/64=64 個組。

    對於32位的內存地址,每一個line有2^6 = 64Byte,因此地址的【0,5】區分line中的那個字節。一共有64個組。咱們取內存地址中間6爲來hash查找地址屬於那個組。即內存地址的【6,11】位來肯定屬於64組的哪個組。組肯定了以後,【12,31】的內存地址與組中8個line挨個比對,若是【12,31】爲與某個line一致,而且這個line爲有效,那麼緩存命中。

    OK,cache分紅三類,
    1 直接映射高速緩存,這個簡單,即每一個組只有一個line,選中組以後不須要和組中的每一個line比對,       由於只有一個line。

    2 組相聯高速緩存,這個就是咱們前面介紹的cache。 S個組,每一個組E個line。

   3 全相聯高速緩存,這個簡單,只有一個組,就是全相聯。不用hash來肯定組,直接挨個比對高位地址,來肯定是否命中。能夠想見這種方式不適合大的緩存。想一想看,若是4M 的大緩存 linesize爲32Byte,採用全相聯的話,就意味着4*1024*1024/32 = 128K 個line挨個比較,來肯定是否命中,這是多要命的事情。高速緩存立馬成了低速緩存了。

   描述一個cache須要如下參數 :
    1 cache分級,L1 cache, L2 cache, L3 cache,級別越低,離cpu越近
    2  cache的容量
    3  cache的linesize
    4  cache 每組的行個數.
    組的個數徹底能夠根據上面的參數計算出來,因此沒有列出來.
    Intel手冊中用這樣的句子來描述cache:
    8-MB L3 Cache, 16-way set associative, 64-byte line size 

    如何獲取cache的參數呢,到了咱們的老朋友cpuid指令,當eax爲0x2的時候,cpuid指令獲取到cache的參數. 下面給出代碼:
#include<stdio.h>
#include<stdlib.h>

int d_eax;
int d_ebx;
int d_ecx;
int d_edx;

int parse_cache()
{
    asm
    (
        "movl $2,%eax\n\t"
        "cpuid\n\t"
        "mov  %eax,d_eax\n\t"
        "mov  %ebx,d_ebx\n\t"
        "mov  %ecx,d_ecx\n\t"
        "mov  %edx,d_edx\n\t"
    );
    printf("d_eax : %x\nd_ebx : %x\nd_ecx : %x\nd_edx : %x\n", d_eax,d_ebx,d_ecx,d_edx);
    return 0;
}
int main()
{
    parse_cache();
    return 0;
}


  1. root@libin :~/program/assembly/cache# ./test
  2. d_eax : 55035a01
  3. d_ebx : f0b2dd
  4. d_ecx : 0
  5. d_edx : 9ca212c
    個人電腦上運行結果如上圖,查看intel的手冊可知
  1. EAX
  2. (55h) Instruction TLB: 2-MB or 4-MB pages, fully associative, 7 entries
  3. (03h) Data TLB: 4-KB Pages, 4-way set associative, 64 entries
  4. (5Ah) Data TLB0: 2-MB or 4-MB pages, 4-way associative, 32 entries
  5. (01h) Instruction TLB: 4-KB Pages, 4-way set associative, 32 entries
  6. EBX:
  7. (F0h) 64-byte Prefetching
  8. (B2h) Instruction TLB: 4-KB pages, 4-way set associative, 64 entries
  9. (DDh) 3rd-level cache: 3-MB, 12-way set associative, 64-byte line size
  10. EDX:
  11. (09h) 1st-level Instruction Cache: 32-KB, 4-way set associative, 64-byte line size
  12. (CAh) Shared 2nd-level TLB: 4-KB pages, 4-way set associative, 512 entries
  13. (21h) 256KB L2 (MLC), 8-way set associative, 64-byte line size
  14. (2Ch) 1st-level data cache: 32-KB, 8-way set associative, 64-byte line size

參考文獻:
1 Intel® Processor Identification andthe CPUID Instruction
2 Professional Assembly Language  Richard Blum著
3 深刻理解計算機系統
相關文章
相關標籤/搜索