亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 操作系統 > 正文

關于CPU Cache -- 程序員需要知道的那些事

2024-06-28 13:21:33
字體:
來源:轉載
供稿:網友
關于CPU Cache -- 程序員需要知道的那些事

本文將介紹一些作為程序猿或者IT從業者應該知道的CPU Cache相關的知識。本章從“為什么會有CPU Cache”,“CPU Cache的大致設計架構”,“幾個認識CPU Cache的實驗”多個方面介紹作為一個程序員所需知道的關于CPU Cache的基礎知識。并通過知識總結出,作為程序員了解這些知識后能對平時開發帶來什么幫助

文章歡迎轉載,但轉載時請保留本段文字,并置于文章的頂部作者:盧鈞軼(cenalulu)本文原文地址:http://cenalulu.github.io/linux/all-about-cpu-cache/

本博客已經遷移至:

http://cenalulu.github.io/

為了更好的體驗,請通過此鏈接閱讀:

http://cenalulu.github.io/linux/all-about-cpu-cache/

先來看一張本文所有概念的一個思維導圖

為什么要有CPU Cache

隨著工藝的提升最近幾十年CPU的頻率不斷提升,而受制于制造工藝和成本限制,目前計算機的內存主要是DRAM并且在訪問速度上沒有質的突破。因此,CPU的處理速度和內存的訪問速度差距越來越大,甚至可以達到上萬倍。這種情況下傳統的CPU通過FSB直連內存的方式顯然就會因為內存訪問的等待,導致計算資源大量閑置,降低CPU整體吞吐量。同時又由于內存數據訪問的熱點集中性,在CPU和內存之間用較為快速而成本較高的SDRAM做一層緩存,就顯得性價比極高了。

為什么要有多級CPU Cache

隨著科技發展,熱點數據的體積越來越大,單純的增加一級緩存大小的性價比已經很低了。因此,就慢慢出現了在一級緩存(L1 Cache)和內存之間又增加一層訪問速度和成本都介于兩者之間的二級緩存(L2 Cache)。下面是一段從What Every PRogrammer Should Know About Memory中摘錄的解釋:

Soon after the introduction of the cache the system got more complicated. The speed difference between the cache and the main memory increased again, to a point that another level of cache was added, bigger and slower than the first-level cache. Only increasing the size of the first-level cache was not an option for economical rea- sons.

此外,又由于程序指令和程序數據的行為和熱點分布差異很大,因此L1 Cache也被劃分成L1i (i for instruction)和L1d (d for data)兩種專門用途的緩存。

什么是Cache Line

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

為了更好的了解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的填充,由于緩存填充的時間遠高于數據訪問的響應時間,因此多一次緩存填充對于總執行的影響會被放大,最終得到下圖的結果:如果讀者有興趣的話也可以在自己的linux或者MAC上通過gcc cache_line_size.c -o cache_line_size編譯,并通過./cache_line_size執行。

了解Cache Line的概念對我們程序猿有什么幫助?我們來看下面這個C語言中常用的循環優化例子下面兩段代碼中,第一段代碼在C語言中總是比第二段代碼的執行速度要快。具體的原因相信你仔細閱讀了Cache Line的介紹后就很容易理解了。

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

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開始編上號。同時64位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(512K)*64=32M的連續熱點數據才會導致一個set內的conflict(Direct Mapped中512K的連續熱點數據就會出現conflict)

addr

為什么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 中的測試結果圖,來解釋下內存對齊在極端情況下帶來的性能損失。memory_align

該圖實際上是我們上文中第一個測試的一個變種??v軸表示了測試對象數組的大小。橫軸表示了每次數組元素訪問之間的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的淘汰策略。常見的淘汰策略主要有LRURandom兩種。通常意義下LRU對于Cache的命中率會比Random更好,所以CPU Cache的淘汰策略選擇的是LRU。當然也有些實驗顯示在Cache Size較大的時候Random策略會有更高的命中率

總結

CPU Cache對于程序猿是透明的,所有的操作和策略都在CPU內部完成。但是,了解和理解CPU Cache的設計、工作原理有利于我們更好的利用CPU Cache,寫出更多對CPU Cache友好的程序

Reference
  1. Gallery of Processor Cache Effects
  2. How Misaligning Data Can Increase Performance 12x by Reducing Cache Misses
  3. Introduction to Caches

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
中文字幕在线精品| 亚洲www在线| 国产成人在线精品| 欧美精品videos| 亚洲欧美另类中文字幕| 青青在线视频一区二区三区| 日本不卡高字幕在线2019| 欧美一级免费看| 夜夜躁日日躁狠狠久久88av| 97色在线观看免费视频| 久久久免费在线观看| 亚洲美女av网站| 欧美色另类天堂2015| 国产91精品久久久| 91精品国产高清| 欧美另类在线播放| 亚洲人成网7777777国产| 日韩成人在线电影网| 久久久久久噜噜噜久久久精品| 成人精品久久久| 久久精品91久久久久久再现| 日韩精品高清在线| 亚洲一区二区久久久久久久| 亚洲午夜久久久久久久| 亚洲另类欧美自拍| 国产日韩亚洲欧美| 亚洲一级免费视频| 成人激情综合网| 亚洲电影在线看| 最近2019免费中文字幕视频三| 亚洲第一免费网站| **欧美日韩vr在线| 国产69精品久久久久久| 一区二区三区高清国产| 日韩欧美国产一区二区| 色综久久综合桃花网| 欧美人在线视频| 91精品国产99久久久久久| 欧美日韩精品中文字幕| 亚洲国产成人在线播放| 欧美视频免费在线观看| 欧美日韩一区二区三区在线免费观看| 亚洲精品资源在线| 亚洲男女性事视频| 午夜精品一区二区三区在线| 国产欧美日韩高清| 久久夜色精品国产亚洲aⅴ| 在线观看日韩www视频免费| 欧美激情成人在线视频| 日韩欧美综合在线视频| 日本精品一区二区三区在线| 成人h片在线播放免费网站| 久久影院在线观看| 深夜福利国产精品| 亚洲成av人片在线观看香蕉| 欧美成人精品一区二区| 亚洲视频axxx| 国产欧美精品va在线观看| 欧美亚洲午夜视频在线观看| 亚洲毛片在线看| 欧美日产国产成人免费图片| 亚洲女同精品视频| 不卡av电影在线观看| 一区二区三区视频免费在线观看| 久久久久久久色| 97久久精品国产| 亚洲国产福利在线| 8x拔播拔播x8国产精品| 欧美激情奇米色| 日韩av最新在线观看| 欧美午夜片欧美片在线观看| 91在线观看免费| 欧美视频在线免费看| 欧美成年人视频网站欧美| 国产97人人超碰caoprom| 在线观看中文字幕亚洲| 国内精久久久久久久久久人| 中文字幕一区二区三区电影| 国产精品丝袜高跟| 国产欧美日韩丝袜精品一区| 日韩性生活视频| 欧美精品在线视频观看| 亚洲www视频| 成人免费在线视频网站| 欧美丰满片xxx777| 国产香蕉精品视频一区二区三区| 亚洲一区二区三区在线视频| 国产女同一区二区| 中文字幕一区日韩电影| 欧美日韩国产成人| 奇米影视亚洲狠狠色| 狠狠综合久久av一区二区小说| 久久精品在线播放| 91性高湖久久久久久久久_久久99| 国产综合在线视频| 久久精品亚洲国产| 992tv成人免费视频| 欧美成aaa人片在线观看蜜臀| 欧美日本高清视频| 亚洲国产免费av| 国产美女精彩久久| 国产拍精品一二三| 成人在线免费观看视视频| 欧美老女人性生活| 欧美日产国产成人免费图片| 日韩av影片在线观看| 亚洲欧美日韩中文视频| 国产精品福利观看| 亚洲国产又黄又爽女人高潮的| 欧美精品久久一区二区| 欧美极品美女视频网站在线观看免费| 亚洲一区二区在线播放| 国产一区二区精品丝袜| 久久久久久亚洲精品中文字幕| 啊v视频在线一区二区三区| 国产999精品久久久| 国产欧美日韩精品丝袜高跟鞋| 日韩视频在线免费| 亚州国产精品久久久| 久久精品一区中文字幕| 欧美老肥婆性猛交视频| 亚洲视频在线观看网站| 久久久免费高清电视剧观看| 久久综合伊人77777尤物| 亚洲一区免费网站| 欧美激情欧美狂野欧美精品| 91亚洲国产成人精品性色| 久久天天躁夜夜躁狠狠躁2022| 国产精品久久久久久久久久ktv| 亚洲一区免费网站| 久久九九全国免费精品观看| 国产成人一区三区| 亚洲国产精品va在线看黑人动漫| 亚洲国产第一页| 欧美在线视频网站| 97碰在线观看| 国产免费成人av| 日韩一区二区福利| 欧洲午夜精品久久久| 精品一区二区亚洲| 日韩风俗一区 二区| 精品视频在线播放| 国产亚洲一区二区在线| 韩国v欧美v日本v亚洲| 欧美激情视频网址| 亚洲精品91美女久久久久久久| 日韩精品亚洲元码| 最近2019年好看中文字幕视频| 色无极影院亚洲| 国产精品久久久久久久av电影| 亚洲欧美成人精品| 另类天堂视频在线观看| 亚洲天堂av在线免费| 97av在线视频| 一二美女精品欧洲| 色综合五月天导航| 国产精品电影一区| 国产精品海角社区在线观看| 精品久久久免费| 日韩有码在线观看| 欧美巨乳在线观看| 91麻豆桃色免费看| 日韩欧美在线字幕| 国产精品美女视频网站|