0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

編譯器的亂序策略

dyquk4xk2p3d ? 來(lái)源:良許Linux ? 2023-05-19 14:46 ? 次閱讀

很多現(xiàn)代高級(jí)語(yǔ)言多提供了多線程并發(fā)技術(shù),今天服務(wù)器CPU基本上都是多核架構(gòu),在Java中,JVM能夠根據(jù)處理器特性(CPU多級(jí)緩存系統(tǒng)、多核處理器等)適當(dāng)對(duì)機(jī)器指令進(jìn)行重排序,最大限度發(fā)揮機(jī)器性能。Java中的指令重排有兩次,第一次發(fā)生在將字節(jié)碼編譯成機(jī)器碼的階段,第二次發(fā)生在CPU執(zhí)行的時(shí)候,也會(huì)適當(dāng)對(duì)指令進(jìn)行重排。

寫這篇文章的目的,是想明確下cpu指令亂序這件事。只要是熟悉計(jì)算機(jī)底層系統(tǒng)的同學(xué)就會(huì)知道,程序里面的每行代碼的執(zhí)行順序,有可能會(huì)被編譯器和cpu根據(jù)某種策略,給打亂掉,目的是為了性能的提升,讓指令的執(zhí)行能夠盡可能的并行起來(lái)

知道指令的亂序策略很重要,原因是這樣我們就能夠通過(guò)barrier(內(nèi)存屏障)等指令,在正確的位置告訴cpu或者是編譯器,這里我可以接受亂序,那里我不能接受亂序等等。從而,能夠在保證代碼正確性的前提下,最大限度地發(fā)揮機(jī)器的性能。

10多年前的程序員對(duì)處理器亂序執(zhí)行內(nèi)存屏障應(yīng)該是很熟悉的,但隨著計(jì)算機(jī)技術(shù)突飛猛進(jìn)的發(fā)展,我們離底層原理越來(lái)越遠(yuǎn),這并不是一件壞事,但在有些情況下了解一些底層原理有助于我們更好的工作,比如現(xiàn)代高級(jí)語(yǔ)言多提供了多線程并發(fā)技術(shù),如果不深入下來(lái),那么有些由多線程造成問(wèn)題就很難排查和理解

前言

這里我不打算討論編譯器的亂序策略,這里討論的指令亂序,含義稍廣些,包括在多核上分別執(zhí)行的指令間,在時(shí)間維度上的亂序。

如果在多核cpu層面考慮亂序執(zhí)行的話,我們要來(lái)梳理清楚以下幾個(gè)概念:單核多核,亂序執(zhí)行順序提交store bufferinvalid queue。最后會(huì)對(duì)x86arm/power架構(gòu)的異同,做一個(gè)總結(jié)。

24a2495e-f5fc-11ed-90ce-dac502259ad0.jpg

單核 vs 多核

從多核的視角上來(lái)說(shuō),是存在著亂序的可能的。比如,假設(shè)存在變量x = 0,cpu0上執(zhí)行寫入W0(x, 1),對(duì)x寫入1。接著在cpu1上,執(zhí)行讀取R1(x, 0),得到x = 0,這在x86和arm/power的cpu上都是可能出現(xiàn)的。原因是x86上cpu核和cache以及內(nèi)存之間,存在著store buffer,當(dāng)W0(x, 1)執(zhí)行成功后,修改只存在于store buffer中,并未寫到cache以及內(nèi)存上,因此cpu1讀取不到最新的x值。對(duì)于arm/power來(lái)說(shuō),同樣也有store buffer,而且還可能會(huì)有invalid queue,導(dǎo)致cpu1讀不到最新的x值。

對(duì)于沒(méi)有invalid queue的x86系列cpu來(lái)說(shuō),當(dāng)修改從store buffer刷入cache時(shí),就能夠保證在其他核上能夠讀到最新的修改。但是,對(duì)于存在invalid queue的cpu來(lái)說(shuō),則不一定。

為了能夠保證多核之間的修改的可見(jiàn)性,我們?cè)趯懗绦虻臅r(shí)候需要加上內(nèi)存屏障,例如x86上的mfence指令。

亂序執(zhí)行 vs 順序提交

我們知道,在cpu中為了能夠讓指令的執(zhí)行盡可能地并行起來(lái),從而發(fā)明了流水線技術(shù)。但是如果兩條指令的前后存在依賴關(guān)系,比如數(shù)據(jù)依賴,控制依賴等,此時(shí)后一條語(yǔ)句就必需等到前一條指令完成后,才能開(kāi)始。

cpu為了提高流水線的運(yùn)行效率,會(huì)做出比如:

1)對(duì)無(wú)依賴的前后指令做適當(dāng)?shù)膩y序和調(diào)度;

2)對(duì)控制依賴的指令做分支預(yù)測(cè);

3)對(duì)讀取內(nèi)存等的耗時(shí)操作,做提前預(yù)讀;

等等。以上總總,都會(huì)導(dǎo)致指令亂序的可能。

但是對(duì)于x86的cpu來(lái)說(shuō),在單核視角上,其實(shí)它做出了Sequential consistency[1]的一致性保障。Sequential consistency的在wiki上的定義如下:

"... the result of any execution is the same as if the operations of all the processors were executed in some sequential order, and the operations of each individual processor appear in this sequence in the order specified by its program."

也就是說(shuō),要滿足Sequential consistency,必需保障每個(gè)處理器的指令執(zhí)行順序必需和程序給出的順序一致。奇怪吧?這不就和我剛才說(shuō)的指令亂序優(yōu)化矛盾了嘛?其實(shí)并不矛盾,指令在cpu核內(nèi)部確實(shí)是亂序執(zhí)行和調(diào)度的,但是它們對(duì)外表現(xiàn)卻是順序提交的。

如果把ISA寄存器(如EAX,EBX等)和store buffer,作為cpu對(duì)外的接口的話,cpu只需要把內(nèi)部真實(shí)的物理寄存器按照指令的執(zhí)行順序,順序映射到ISA寄存器上,也就是cpu只要將結(jié)果順序地提交到ISA寄存器,就可以保證Sequential consistency。

當(dāng)然,以上是對(duì)x86架構(gòu)的cpu來(lái)說(shuō)的,ARM/Power架構(gòu)的cpu在單核上的一致性保證要弱一些,無(wú)需保證Sequential consistency,因此也不需要順序提交,只需保證控制依賴,數(shù)據(jù)依賴,地址依賴等指令的順序即可。要想在這些弱一致性模型cpu下保證無(wú)關(guān)指令間的提交順序,需要使用barrier指令。

Store Buffer & Invalid Queue

store buffer存在于cpu核與cache之間,對(duì)于x86架構(gòu)來(lái)說(shuō),store buffer是FIFO,因此不會(huì)存在亂序,寫入順序就是刷入cache的順序。但是對(duì)于ARM/Power架構(gòu)來(lái)說(shuō),store buffer并未保證FIFO,因此先寫入store buffer的數(shù)據(jù),是有可能比后寫入store buffer的數(shù)據(jù)晚刷入cache的。從這點(diǎn)上來(lái)說(shuō),store buffer的存在會(huì)讓ARM/Power架構(gòu)出現(xiàn)亂序的可能。store barrier存在的意義就是將store buffer中的數(shù)據(jù),刷入cache。

在某些cpu中,存在invalid queue。invalid queue用于緩存cache line的失效消息,也就是說(shuō),當(dāng)cpu0寫入W0(x, 1),并從store buffer將修改刷入cache,此時(shí)cpu1讀取R1(x, 0)仍是允許的。因?yàn)槭筩ache line失效的消息被緩沖在了invalid queue中,還未被應(yīng)用到cache line上。這也是一種會(huì)使得指令亂序的可能。load barrier存在的意義就是將invalid queue緩沖刷新。

X86 vs ARM/Power

對(duì)于x86架構(gòu)的cpu來(lái)說(shuō),在單核上來(lái)看,其保證了Sequential consistency,因此對(duì)于開(kāi)發(fā)者,我們可以完全不用擔(dān)心單核上的亂序優(yōu)化會(huì)給我們的程序帶來(lái)正確性問(wèn)題。在多核上來(lái)看,其保證了x86-tso模型,使用mfence就可以將store buffer中的數(shù)據(jù),寫入到cache中。而且,由于x86架構(gòu)下,store buffer是FIFO的和不存在invalid queue,mfence能夠保證多核間的數(shù)據(jù)可見(jiàn)性,以及順序性。[2]

對(duì)于arm和power架構(gòu)的cpu來(lái)說(shuō),編程就變得危險(xiǎn)多了。除了存在數(shù)據(jù)依賴,控制依賴以及地址依賴等的前后指令不能被亂序之外,其余指令間都有可能存在亂序。而且,它們的store buffer并不是FIFO的,而且還可能存在invalid queue,這些也同樣讓并發(fā)編程變得困難重重。因此需要引入不同類型的barrier來(lái)完成不同的需求。[3]

總結(jié)

從上面的介紹可以知道,開(kāi)發(fā)者想要做好并發(fā)編程是多么困難的事情,但是我們至少跨出了第一步,也就是定義困難本身。

審核編輯:彭靜
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 處理器
    +關(guān)注

    關(guān)注

    68

    文章

    19384

    瀏覽量

    230488
  • 計(jì)算機(jī)
    +關(guān)注

    關(guān)注

    19

    文章

    7525

    瀏覽量

    88318
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1639

    瀏覽量

    49197

原文標(biāo)題:當(dāng)我們?cè)谡務(wù)?cpu 指令亂序的時(shí)候,究竟在談?wù)撌裁矗?/p>

文章出處:【微信號(hào):良許Linux,微信公眾號(hào):良許Linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    ICC AVR編譯器的安裝與使用

    ICCAVR編譯器的安裝、運(yùn)行、破解、使用 用ICCAVR編譯器產(chǎn)生初始化程序和程序框架
    發(fā)表于 07-09 18:06 ?258次下載

    基于CoSy的編譯器開(kāi)發(fā)的研究

    CoSy是ACE公司開(kāi)發(fā)的編譯器構(gòu)造框架[1]。它提供共享工具和引擎來(lái)構(gòu)造編譯器,編譯器開(kāi)發(fā)者只專注于目標(biāo)機(jī)相關(guān)代碼的開(kāi)發(fā)。CoSy框架生成的編譯器具有可擴(kuò)展性和可移植性??梢愿鶕?jù)目
    發(fā)表于 08-19 17:49 ?0次下載
    基于CoSy的<b class='flag-5'>編譯器</b>開(kāi)發(fā)的研究

    PICC編譯器下載

    PICC編譯器下載
    發(fā)表于 05-25 17:44 ?168次下載

    NEC編譯器培訓(xùn)手冊(cè)

    NEC編譯器培訓(xùn)手冊(cè),開(kāi)發(fā)者可根據(jù)功能要求對(duì)編譯器進(jìn)行設(shè)計(jì)。
    發(fā)表于 05-03 14:23 ?15次下載

    編譯器是如何工作的_編譯器的工作過(guò)程詳解

    隨著計(jì)算機(jī)的發(fā)展,編譯器已經(jīng)發(fā)揮著十分重要的作用。本文主要介紹了編譯器的種類、編譯器的工作原理以及編譯器工作的具體操作過(guò)程及步驟詳解。
    發(fā)表于 12-19 12:54 ?1.6w次閱讀

    編譯器原理到底是怎樣的帶你簡(jiǎn)單的了解編譯器原理

    編程語(yǔ)言是怎樣工作的 理解編譯器內(nèi)部原理,可以讓你更高效利用它。按照編譯的工作順序,逐步深入編程語(yǔ)言和編譯器是怎樣工作的。本文有大量的鏈接、樣例代碼和圖表幫助你理解編譯器。
    的頭像 發(fā)表于 12-23 17:25 ?1.1w次閱讀

    Verilog HDL 編譯器指令說(shuō)明

    Verilog HDL 編譯器指令 復(fù)雜一點(diǎn)的系統(tǒng)在進(jìn)行設(shè)計(jì)或者驗(yàn)證時(shí),都會(huì)用到一些編譯器指令,那么什么是編譯器指令? ? Verilog HDL編譯器指令由重音符(‘)開(kāi)始。在Ver
    的頭像 發(fā)表于 11-03 09:31 ?3805次閱讀
    Verilog HDL <b class='flag-5'>編譯器</b>指令說(shuō)明

    GH集成開(kāi)發(fā)環(huán)境和編譯器

    說(shuō)實(shí)話,以前也用過(guò)正版的編譯器,我記得之前用過(guò)正版的IAR編譯器license也沒(méi)有多貴,而最近用了個(gè)10萬(wàn)一個(gè)license的編譯器編譯嵌入式代碼,因?yàn)閷?duì)功能安全有要求,而這個(gè)Gre
    的頭像 發(fā)表于 03-16 17:08 ?1746次閱讀

    交叉編譯器安裝教程

    交叉編譯器中“交叉”的意思就是在一個(gè)架構(gòu)上編譯另外一個(gè)架構(gòu)的代碼,相當(dāng)于兩種架構(gòu)“交叉”起來(lái)了。Ubuntu 自帶的 gcc 編譯器是針對(duì) X86 架構(gòu)的,而我們現(xiàn)在要編譯的是 ARM
    的頭像 發(fā)表于 09-29 09:12 ?3554次閱讀

    領(lǐng)域編譯器發(fā)展的前世今生

    近年來(lái),隨著GPU和DSA架構(gòu)在不同領(lǐng)域的廣泛應(yīng)用,特別是AI系統(tǒng)相關(guān)技術(shù)的飛速發(fā)展,對(duì)于編譯器的需求越來(lái)越強(qiáng)烈。編譯器已經(jīng)從一個(gè)相對(duì)小眾的研究領(lǐng)域,變?yōu)閷W(xué)界和業(yè)界都高度關(guān)注并大量投入的方向
    的頭像 發(fā)表于 02-03 10:37 ?1747次閱讀

    當(dāng)我們?cè)谡務(wù)揷pu指令亂序的時(shí)候,究竟在談?wù)撌裁矗?/a>

    知道指令的亂序策略很重要,原因是這樣我們就能夠通過(guò)barrier(內(nèi)存屏障)等指令,在正確的位置告訴cpu或者是編譯器,這里我可以接受亂序,那里我不能接受
    的頭像 發(fā)表于 05-19 14:42 ?1383次閱讀
    當(dāng)我們?cè)谡務(wù)揷pu指令<b class='flag-5'>亂序</b>的時(shí)候,究竟在談?wù)撌裁矗? />    </a>
</div>                            <div   id=

    人工智能編譯器與傳統(tǒng)編譯器的區(qū)別

    人工智能編譯器(AI編譯器)與傳統(tǒng)編譯器在多個(gè)方面存在顯著的差異。這些差異主要體現(xiàn)在設(shè)計(jì)目標(biāo)、功能特性、優(yōu)化策略、適用范圍以及技術(shù)復(fù)雜性等方面。以下是對(duì)兩者區(qū)別的詳細(xì)探討,旨在全面解析
    的頭像 發(fā)表于 07-17 18:19 ?2008次閱讀

    Triton編譯器功能介紹 Triton編譯器使用教程

    Triton 是一個(gè)開(kāi)源的編譯器前端,它支持多種編程語(yǔ)言,包括 C、C++、Fortran 和 Ada。Triton 旨在提供一個(gè)可擴(kuò)展和可定制的編譯器框架,允許開(kāi)發(fā)者添加新的編程語(yǔ)言特性和優(yōu)化技術(shù)
    的頭像 發(fā)表于 12-24 17:23 ?493次閱讀

    Triton編譯器與其他編譯器的比較

    Triton編譯器與其他編譯器的比較主要體現(xiàn)在以下幾個(gè)方面: 一、定位與目標(biāo) Triton編譯器 : 定位:專注于深度學(xué)習(xí)中最核心、最耗時(shí)的張量運(yùn)算的優(yōu)化。 目標(biāo):提供一個(gè)高度抽象、靈活、高效
    的頭像 發(fā)表于 12-24 17:25 ?414次閱讀

    Triton編譯器的優(yōu)化技巧

    在現(xiàn)代計(jì)算環(huán)境中,編譯器的性能對(duì)于軟件的運(yùn)行效率至關(guān)重要。Triton 編譯器作為一個(gè)先進(jìn)的編譯器框架,提供了一系列的優(yōu)化技術(shù),以確保生成的代碼既高效又適應(yīng)不同的硬件架構(gòu)。 1. 指令選擇
    的頭像 發(fā)表于 12-25 09:09 ?266次閱讀