cpu緩存與多線程

1、cpu緩存結構

    CPU速度遠高於內存(即若是隻考慮CPU和內存因素,程序的性能經常受到內存訪問速度的限制,內存訪問和運行),爲了協調CPU和內存在速度上的差別,在CPU中增長了高速緩存。和計算機存儲金字塔結構相似,高速緩存也能夠按照金字塔結構,從下到上越接近CPU速度越快,同時容量也越小。如今大部分的處理器都有二級或者三級緩存,從下到上依次爲 L3 cache, L2 cache, L1 cache. 緩存又能夠分爲指令緩存和數據緩存,指令緩存用來緩存程序的代碼,數據緩存用來緩存程序的數據。 
    單核CPU只含有一套L1,L2,L3緩存;若是CPU含有多個核心,即多核CPU,則每一個核心都含有一套L1(甚至和L2)緩存,而共享L3(或者和L2)緩存。多CPU,每一個CPU都相互獨立,擁有本身的緩存,CPU之間沒法共享緩存。 下圖爲一個單CPU雙核的緩存結構。 
                        
html

緩存行 cache line 
    緩存行時緩存和內存交換數據的最小單位,通常爲64字節。即每次緩存和內存之間進行數據交換的時候,都是以字節對齊的連續64字節的內存塊整個進行。
shell

緩存訪問 
    沒有緩存的結構中,CPU執行進程的時候,使用虛擬地址,虛擬地址經過MMU翻譯爲物理地址,映射到內存中;在有緩存的結構中,CPU訪問數據先查找緩存中是否存在該數據,這能夠經過數據在進程中的虛擬地址去到緩存中查找,也能夠經過該數據在內存中的物理地址去到緩存中查找。 
    所以,緩存中的數據既能夠經過數據在進程空間中的虛擬地址檢索,也能夠經過數據的實際內存物理地址來檢索。若是經過進程空間中的虛擬地址,那麼多個不一樣進程可能含有相同的虛擬地址,所以實際中還須要在緩存行中添加 ASID(address space identifier) the hardware version of a process ID,這樣CPU在運行不一樣進程的時候,就能夠經過 虛擬地址+ASID 在cache中進行查找; 
    若是緩存經過物理地址來檢索,那麼須要MMU介於CPU和cache中間來進行地址的翻譯,這樣就下降了cache查找的速率,所以通常 L1 cache不能經過物理地址檢索,而是經過虛擬地址,由CPU直接訪問。而L2,L3 cache能夠經過物理內存地址檢索
緩存

TLB 快表 
    MMU進行虛擬地址到物理地址的映射,經過頁表將虛擬地址翻譯爲物理地址。TLB位於MMU內部,不須要通過頁表就能夠將虛擬地址轉換爲物理地址,速度更快。 
    每個TLB寄存器的每一個條目包含一個頁面的信息:有效位,虛頁面號,修改位,保護碼,和頁面所在的物理頁面號,它們和頁面表中的表項一一對應。 
MMU在翻譯的時候,先查看虛擬地址的虛擬頁面號是否存在TLB(並行的查找)中,若是存在,且沒有違背讀寫權限限制,則直接給出TLB中的物理頁面號;若在TLB中不存在,則進行常規的頁表的查找,而後從TLB中淘汰一個條目,並更新爲剛剛查找的頁面。
多線程

多線程場景下的緩存

    在單線程模式下,一塊內存只對應一個cpu核心的緩存,且只被一個線程訪問。緩存獨佔,不會出現訪問衝突等問題。 
    在多線程模式下,一個CPU,且CPU單核,進程中的多個線程會同時訪問進程中的共享數據,CPU將某塊內存加載到緩存後,不一樣線程在訪問相同的物理地址的時候,都會映射到相同的緩存位置,這樣即便發生線程的切換,緩存仍然不會失效。但因爲任什麼時候刻只能有一個線程在執行,所以不會出現緩存訪問衝突。固然,因爲CPU內部寄存器的存在,會有多線程下的 A++ 非原子性語句致使的問題。 
 
    A++ ==> 
    reg = (&A); 
    reg ++; 
    
(&A) = reg; 
在發生線程切換的時候,線程使用的內部寄存器會被做爲現場進行保存。 
 
    多線程模式下,一個CPU,且CPU有多核,每一個核都至少有一個L1 cache。多個線程訪問進程中的某個共享內存,且這多個線程分別在不一樣的核心上執行,則每一個核心都會在各自的caehe中保留一份共享內存的緩衝。因爲多核能夠作到真並行,可能會出現多個線程同時寫各自的cache, 
    所以CPU有「緩存一致性」原則,即每一個處理器(核)都會經過嗅探在總線上傳播的數據來檢查本身的緩存值是否是過時了,當處理器發現本身緩存行對應的內存地址被修改,就會將當前處理器(核)。所以,咱們常常看到在多核多線程的場景下,在聲明變量時候使用volatile,volatile變量要求在更新了緩存以後當即寫入到系統內存,而非volatile變量,則是CPU修改緩存,緩存在適當的識貨(不知道何時)將緩存數據寫入內存。寫入內存的操做會出發其餘處理器(核)將本身已經緩存的那塊正在被寫入的內存失效,並在下次須要使用到該內存的時候從新從內存讀取。
ide

False Sharing(僞共享) 
    因爲緩存按照最小單位緩存行進行和內存交互,緩存行通常爲64字節。內存中的連續64字節會被加載到一個緩存行中。當多線程修改互相獨立的變量時,若是這些變量共享同一個緩存行,就會無心中影響彼此的性能,這就是僞共享。 
            
性能

    如上圖所示,X和Y被放在同一緩存行中,當core1 修改x的時候,爲了線程間可見性,須要鎖定緩存行;此時core2中的緩存行也跟着失效;一樣,core2中修改y時候,也須要鎖定緩存行,core1中的緩存行也跟着失效。影響效率。spa

相關文章
相關標籤/搜索