欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談C++性能榨汁機(jī)之偽共享

 更新時(shí)間:2021年06月09日 10:52:25   作者:lsgxeva  
使給定內(nèi)存位置被一個(gè)線(xiàn)程所訪問(wèn),可能還是會(huì)有乒乓緩存的存在,是因?yàn)榱硪环N叫做偽共享(false sharing)的效應(yīng)。即使數(shù)據(jù)存儲(chǔ)在緩存行中,多個(gè)線(xiàn)程對(duì)數(shù)據(jù)中的成員進(jìn)行訪問(wèn)時(shí),硬件緩存還是會(huì)產(chǎn)生乒乓緩存。本文將介紹C++中的偽共享

前言

在多核并發(fā)編程中,如果將互斥鎖的爭(zhēng)用比作“性能殺手”的話(huà),那么偽共享則相當(dāng)于“性能刺客”?!皻⑹帧迸c“刺客”的區(qū)別在于殺手是可見(jiàn)的,遇到殺手時(shí)我們可以選擇戰(zhàn)斗、逃跑、繞路、求饒等多種手段去應(yīng)付,但“刺客”卻不同,“刺客”永遠(yuǎn)隱藏在暗處,伺機(jī)給你致命一擊,防不勝防。具體到我們的并發(fā)編程中,遇到鎖爭(zhēng)用影響并發(fā)性能情況時(shí),我們可以采取多種措施(如縮短臨界區(qū),原子操作等等)去提高程序性能,但是偽共享卻是我們從所寫(xiě)代碼中看不出任何蛛絲馬跡的,發(fā)現(xiàn)不了問(wèn)題也就無(wú)法解決問(wèn)題,從而導(dǎo)致偽共享在“暗處”嚴(yán)重拖累程序的并發(fā)性能,但我們卻束手無(wú)策。

緩存行

為了進(jìn)行下面的討論,我們需要首先熟悉緩存行的概念,學(xué)過(guò)操作系統(tǒng)課程存儲(chǔ)結(jié)構(gòu)這部分內(nèi)容的同學(xué)應(yīng)該對(duì)存儲(chǔ)器層次結(jié)構(gòu)的金字塔模型印象深刻,金字塔從上往下代表存儲(chǔ)介質(zhì)的成本降低、容量變大,從下往上則代表存取速度的提高。位于金字塔模型最上層的是CPU中的寄存器,其次是CPU緩存(L1,L2,L3),再往下是內(nèi)存,最底層是磁盤(pán),操作系統(tǒng)采用這種存儲(chǔ)層次模型主要是為了解決CPU的高速與內(nèi)存磁盤(pán)低速之間的矛盾,CPU將最近使用的數(shù)據(jù)預(yù)先讀取到Cache中,下次再訪問(wèn)同樣數(shù)據(jù)的時(shí)候,可以直接從速度比較快的CPU緩存中讀取,避免從內(nèi)存或磁盤(pán)讀取拖慢整體速度。

CPU緩存的最小單位就是緩存行,緩存行大小依據(jù)架構(gòu)不同有不同大小,最常見(jiàn)的有64Byte和32Byte,CPU緩存從內(nèi)存取數(shù)據(jù)時(shí)以緩存行為單位進(jìn)行,每一次都取需要讀取數(shù)據(jù)所在的整個(gè)緩存行,即使相鄰的數(shù)據(jù)沒(méi)有被用到也會(huì)被緩存到CPU緩存中(這里又涉及到局部性原理,后面文章會(huì)進(jìn)行介紹)。

緩存一致性

在單核CPU情況下,上述方法可以正常工作,可以確保緩存到CPU緩存中的數(shù)據(jù)永遠(yuǎn)是“干凈”的,因?yàn)椴粫?huì)有其他CPU去更改內(nèi)存中的數(shù)據(jù),但是在多核CPU下,情況就變得更加復(fù)雜一些。多CPU中,每個(gè)CPU都有自己的私有緩存(可能共享L3緩存),當(dāng)一個(gè)CPU1對(duì)Cache中緩存數(shù)據(jù)進(jìn)行操作時(shí),如果CPU2在此之前更改了該數(shù)據(jù),則CPU1中的數(shù)據(jù)就不再是“干凈”的,即應(yīng)該是失效數(shù)據(jù),緩存一致性就是為了保證多CPU之間的緩存一致。

Linux系統(tǒng)中采用MESI協(xié)議處理緩存一致性,所謂MESI即是指CPU緩存的四種狀態(tài):

  • M(修改,Modified):本地處理器已經(jīng)修改緩存行,即是臟行,它的內(nèi)容與內(nèi)存中的內(nèi)容不一樣,并且此 cache 只有本地一個(gè)拷貝(專(zhuān)有);
  • E(專(zhuān)有,Exclusive):緩存行內(nèi)容和內(nèi)存中的一樣,而且其它處理器都沒(méi)有這行數(shù)據(jù);
  • S(共享,Shared):緩存行內(nèi)容和內(nèi)存中的一樣, 有可能其它處理器也存在此緩存行的拷貝;
  • I(無(wú)效,Invalid):緩存行失效, 不能使用。

每個(gè)CPU緩存行都在四個(gè)狀態(tài)之間互相轉(zhuǎn)換,以此決定CPU緩存是否失效,比如CPU1對(duì)一個(gè)緩存行執(zhí)行了寫(xiě)入操作,則此操作會(huì)導(dǎo)致其他CPU的該緩存行進(jìn)入Invalid無(wú)效狀態(tài),CPU需要使用該緩存行的時(shí)候需要從內(nèi)存中重新讀取。由此就解決了多CPU之間的緩存一致性問(wèn)題。

偽共享

何謂偽共享?上面我們提過(guò)CPU的緩存是以緩存行為單位進(jìn)行的,即除了本身所需讀寫(xiě)的數(shù)據(jù)之外還會(huì)緩存與該數(shù)據(jù)在同一緩存行的數(shù)據(jù),假設(shè)緩存行大小是32字節(jié),內(nèi)存中有“abcdefgh”八個(gè)int型數(shù)據(jù),當(dāng)CPU讀取“d”這個(gè)數(shù)據(jù)時(shí),CPU會(huì)將“abcdefgh”八個(gè)int數(shù)據(jù)組成一個(gè)緩存行加入到CPU緩存中。假設(shè)計(jì)算機(jī)有兩個(gè)CPU:CPU1和CPU2,CPU1只對(duì)“a”這個(gè)數(shù)據(jù)進(jìn)行頻繁讀寫(xiě),CPU2只對(duì)“b”這個(gè)數(shù)據(jù)進(jìn)行頻繁讀寫(xiě),按理說(shuō)這兩個(gè)CPU讀寫(xiě)數(shù)據(jù)沒(méi)有任何關(guān)聯(lián),也就不會(huì)產(chǎn)生任何競(jìng)爭(zhēng),不會(huì)有性能問(wèn)題,但是由于CPU緩存是以緩存行為單位進(jìn)行存取的,也是以緩存行為單位失效的,即使CPU1只更改了緩存行中“a”數(shù)據(jù),也會(huì)導(dǎo)致CPU2中該緩存行完全失效,同理,CPU2對(duì)“b”的改動(dòng)也會(huì)導(dǎo)致CPU1中該緩存行失效,由此引發(fā)了該緩存行在兩個(gè)CPU之間“乒乓”,緩存行頻繁失效,最終導(dǎo)致程序性能下降,這就是偽共享。

如何避免偽共享

避免偽共享主要有以下兩種方式:

1.緩存行填充(Padding):為了避免偽共享就需要將可能造成偽共享的多個(gè)變量處于不同的緩存行中,可以采用在變量后面填充字節(jié)的方式達(dá)到該目的。

2.使用某些語(yǔ)言或編譯器中強(qiáng)制變量對(duì)齊,將變量都對(duì)齊到緩存行大小,避免偽共享發(fā)生。

總結(jié)

一般偽共享都很隱蔽,很難被發(fā)現(xiàn),當(dāng)偽共享真正構(gòu)成性能瓶頸的時(shí)候,我們有必要去努力找到并解決它,但是在大部分對(duì)性能追求沒(méi)有那么高的應(yīng)用中,偽共享的存在對(duì)程序的危害很小,有時(shí)并不值得耗費(fèi)精力和額外的內(nèi)存空間(緩存行填充)去查找系統(tǒng)存在的偽共享。還是那句我一直以來(lái)遵循的話(huà)“不要過(guò)度優(yōu)化,不要提前優(yōu)化?!?。

以上就是淺談C++性能榨汁機(jī)之偽共享的詳細(xì)內(nèi)容,更多關(guān)于C++性能榨汁機(jī)之偽共享的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • C++實(shí)現(xiàn)LeetCode(139.拆分詞句)

    C++實(shí)現(xiàn)LeetCode(139.拆分詞句)

    這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(139.拆分詞句),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-07-07
  • C++中的string類(lèi)型

    C++中的string類(lèi)型

    這篇文章主要介紹了C++中的string類(lèi)型,在C++當(dāng)中,除了char 類(lèi)型,還有專(zhuān)門(mén)的字符串類(lèi)型,就叫做string,下面文字將圍繞其相關(guān)資料展開(kāi)詳細(xì)內(nèi)容,需要的朋友可以參考一下,希望對(duì)你有所幫助
    2021-11-11
  • C++中友元類(lèi)和嵌套類(lèi)使用詳解

    C++中友元類(lèi)和嵌套類(lèi)使用詳解

    友元是一種允許非類(lèi)成員函數(shù)訪問(wèn)類(lèi)的非公有成員的一種機(jī)制??梢园岩粋€(gè)函數(shù)指定為類(lèi)的友元,也可以把整個(gè)類(lèi)指定為另一個(gè)類(lèi)的友元,所謂嵌套類(lèi),就是在類(lèi)中聲明的類(lèi)。如下代碼中,類(lèi)Inner就是一個(gè)嵌套類(lèi),類(lèi)Outer是外圍類(lèi)
    2022-08-08
  • C語(yǔ)言直接插入排序算法介紹及示例

    C語(yǔ)言直接插入排序算法介紹及示例

    插入排序是把一個(gè)記錄插入到已排序的有序序列中,使整個(gè)序列在插入該記錄后仍然有序。插入排序中較簡(jiǎn)單的種方法是直接插入排序,其插入位置的確定方法是將待插入的記錄與有序區(qū)中的各記錄自右向左依次比較其關(guān)鍵字值的大小
    2022-08-08
  • 淺談C++反向迭代器的設(shè)計(jì)

    淺談C++反向迭代器的設(shè)計(jì)

    本文主要介紹了淺談C++反向迭代器的設(shè)計(jì),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • Sublime Text 3 實(shí)現(xiàn)C語(yǔ)言代碼的編譯和運(yùn)行(示例講解)

    Sublime Text 3 實(shí)現(xiàn)C語(yǔ)言代碼的編譯和運(yùn)行(示例講解)

    下面小編就為大家?guī)?lái)一篇Sublime Text 3 實(shí)現(xiàn)C語(yǔ)言代碼的編譯和運(yùn)行(示例講解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-09-09
  • C++ 11 nullptr 空指針示例詳解

    C++ 11 nullptr 空指針示例詳解

    C++11標(biāo)準(zhǔn)引入了nullptr來(lái)替代傳統(tǒng)的NULL,解決了NULL可能導(dǎo)致的類(lèi)型混淆問(wèn)題,nullptr是nullptr_t類(lèi)型的實(shí)例,專(zhuān)用于初始化空類(lèi)型指針,與整型不會(huì)發(fā)生隱式轉(zhuǎn)換,從而使代碼更健壯,它可以被隱式轉(zhuǎn)換為任意類(lèi)型的指針,提高了代碼的安全性和可讀性
    2024-10-10
  • 《C++ Primer》隱式類(lèi)類(lèi)型轉(zhuǎn)換學(xué)習(xí)整理

    《C++ Primer》隱式類(lèi)類(lèi)型轉(zhuǎn)換學(xué)習(xí)整理

    在本篇文章里小編給大家整理的是關(guān)于《C++ Primer》隱式類(lèi)類(lèi)型轉(zhuǎn)換學(xué)習(xí)筆記內(nèi)容,需要的朋友們參考下。
    2020-02-02
  • Dev-C++無(wú)法使用bits/stdc++.h問(wèn)題及解決

    Dev-C++無(wú)法使用bits/stdc++.h問(wèn)題及解決

    這篇文章主要介紹了Dev-C++無(wú)法使用bits/stdc++.h問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Qt基于定時(shí)器實(shí)現(xiàn)動(dòng)圖展示效果

    Qt基于定時(shí)器實(shí)現(xiàn)動(dòng)圖展示效果

    這篇文章主要為大家詳細(xì)介紹了Qt基于定時(shí)器實(shí)現(xiàn)簡(jiǎn)單動(dòng)圖展示,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-06-06

最新評(píng)論