一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

如何解決像亂序執(zhí)行又像內(nèi)存屏障的BUG

程序人生 ? 來(lái)源:CSDN博客 ? 作者:馬超 ? 2021-07-26 09:32 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

單核環(huán)境y也是0:其中一位非常細(xì)心的讀者針對(duì)這個(gè)多核競(jìng)爭(zhēng)造成問(wèn)題的結(jié)論進(jìn)行了驗(yàn)證,親身在單核的環(huán)境ECS上實(shí)驗(yàn),結(jié)果發(fā)現(xiàn)結(jié)果照樣y=0。

后發(fā)先至:另外一位讀者則給出了一個(gè)更奇怪的現(xiàn)象,兩個(gè)變量中后執(zhí)行的代碼看起來(lái)卻先被調(diào)用了。

加個(gè)if問(wèn)題竟然解了:最后一個(gè)反饋留言最令人崩潰,在代碼中隨便加上個(gè)判斷語(yǔ)句,不但解決了y=0的問(wèn)題,性能還非常好。

1難道這就是傳說(shuō)中的亂序執(zhí)行?

先來(lái)看以下讀者回復(fù)的代碼:

package main import (“fmt”“sync/atomic”“time”) func main() {var x int32var y int32 go func() {for { x = atomic.AddInt32(&x, 1) y = atomic.AddInt32(&y, 1) } }() time.Sleep(time.Second) fmt.Println(“x=”, x) fmt.Println(“y=”, y)}

在這部分內(nèi)容中,兩個(gè)變量x和y都是由原子操作Automic.Add來(lái)保證并發(fā)安全的,但是結(jié)果輸出出來(lái)我們可以發(fā)現(xiàn)y竟然比x還大?而且每次運(yùn)行的情況基本都是y更大,只是大多少有所區(qū)別。

x= 49418397y= 49425282成功: 進(jìn)程退出代碼 0.

看到這個(gè)輸出結(jié)果,我第一反應(yīng)感覺(jué)這是亂序執(zhí)行的衍生現(xiàn)象,因?yàn)閤和y的加1操作彼此是獨(dú)立的,雖然編譯器不會(huì)優(yōu)化執(zhí)行順序,但是在CPU的執(zhí)行層面有可能會(huì)對(duì)于前后無(wú)依賴的操作打亂順序執(zhí)行。這樣一來(lái)就的確有可能出現(xiàn)后面的操作先執(zhí)行的情況。

但是仔細(xì)一想這樣的說(shuō)法應(yīng)該并不合理,如果是亂序執(zhí)行的原因,那么上面這段代碼的執(zhí)行結(jié)果肯定不會(huì)每次結(jié)果都是y更大一些,每次執(zhí)行都是y比x更大只能說(shuō)明代碼是按照一定順序執(zhí)行的,而且目前的CPU指令流水線的預(yù)測(cè)功能肯定還沒(méi)有牛到能夠完全知曉x與y的值不按照順序提交是沒(méi)有作何影響的地步。

2仔細(xì)一看還是多并發(fā)競(jìng)爭(zhēng)問(wèn)題

再來(lái)看以下代碼,

package main import (“fmt”“sync/atomic”“time”) func main() {var x int32var y int32 go func() {for { x = atomic.AddInt32(&x, 1) y = atomic.AddInt32(&y, 1) } }() time.Sleep(time.Second) x1 := x y1 := y fmt.Println(“x=”, x1) fmt.Println(“y=”, y1)}

只要把fmt.println之前先把x和y的值拷貝出來(lái)到x1與y1,再打印x1與y1的值就基本沒(méi)有這個(gè)誤差了。

x= 51061072y= 51061071成功: 進(jìn)程退出代碼 0.

這也就是說(shuō),fmt.println在執(zhí)行中間,go func中的子gorouine又被調(diào)度了。所以y比x的值大,本質(zhì)又是一個(gè)多并發(fā)的競(jìng)爭(zhēng)問(wèn)題。而不是亂序執(zhí)行的原因,只是這個(gè)問(wèn)題在Go的開(kāi)發(fā)模式下也是非常隱蔽。

3崩潰了,單核怎么也是0

再說(shuō)第二個(gè)令人崩潰的讀者反饋,他在單核的云ECS嘗試運(yùn)行以下代碼,

package main import (“fmt”//“sync/atomic”“time”) func main() {var x int32var y int32 go func() {for { x++ y++ } }() time.Sleep(time.Second) fmt.Println(“x=”, x) fmt.Println(“y=”, y)}

結(jié)果也是0。剛開(kāi)始我覺(jué)得這個(gè)讀者反饋有誤,因此我也立刻在阿里云的X86集群與華為云的鯤鵬集群分別申請(qǐng)了一臺(tái)單核ECS,不過(guò)結(jié)果令人崩潰,無(wú)論是ARM還是X86單核平臺(tái)運(yùn)行上述代表的結(jié)果也還是0,不過(guò)這還沒(méi)完。

4更崩潰了,隨隨便便加個(gè)if竟然殺瘋了…。

接下來(lái)是最令人崩潰的時(shí)刻,我們來(lái)看以下代碼:

package main import (“fmt”//“sync/atomic”“time”) func main() {var x int32var y int32 z := 0 go func() {for { x++//一些無(wú)需關(guān)注并發(fā)安全的計(jì)算問(wèn)題 y++if z 》 0 { fmt.Println(“z is”, z)//這一行代碼不會(huì)執(zhí)行到 } } }() time.Sleep(time.Second)//定時(shí)執(zhí)行,超過(guò)1秒鐘就停止了,無(wú)需關(guān)注并發(fā)安全 fmt.Println(“x=”, x) fmt.Println(“y=”, y)}

這段代碼在沒(méi)有作何鎖或者互斥體的基礎(chǔ)上竟然解決了y=0的問(wèn)題,而且令人崩潰的是,這段代碼的執(zhí)行效率竟然還非常驚人,比之前Automic的方式至少快一個(gè)數(shù)量級(jí),

如果是這樣的話那么這種代碼方案就非常適合于不需要并發(fā)控制,并且定時(shí)需要結(jié)束的計(jì)算場(chǎng)景,假如我一個(gè)計(jì)算任務(wù)只能給1秒鐘,能算得出來(lái)就算,算不出來(lái)就解下一題了,那么if的方案就非常適合了。

x= 407698730y= 407745938成功: 進(jìn)程退出代碼 0.

在解釋if分支這個(gè)非主流的方案之前,我們?cè)賮?lái)看一下互斥體這種主流并發(fā)同步方案。

互斥體實(shí)現(xiàn)如下:

package main import (“fmt”“sync” //“sync/atomic”“time”) func main() {var x int32var y int32var mutex sync.Mutex go func() {for { mutex.Lock() x++ y++ mutex.Unlock() } }() time.Sleep(time.Second) x1 := x y1 := y fmt.Println(“x=”, x1) fmt.Println(“y=”, y1)}

運(yùn)行結(jié)果如下:

x= 50889322y= 50889322成功: 進(jìn)程退出代碼 0.

我們可以看到互斥、原子操作等方法最終運(yùn)行結(jié)果基本都在一個(gè)數(shù)量級(jí)以內(nèi)上下浮動(dòng),幅度不超過(guò)10%,對(duì)比之下if的方案實(shí)在是殺瘋了,直接比上述這種安全的寫法性能好出一個(gè)數(shù)量級(jí)!隨便加入個(gè)if分支,竟然也能解決y=0,而且還是高效解決這到底是為什么?

5關(guān)鍵時(shí)刻匯編令人心安,大神一語(yǔ)道破

在我的知識(shí)儲(chǔ)備實(shí)在無(wú)法解釋以上現(xiàn)象的時(shí)候,我只能將希望訴諸objdump,將gobuild生成的可執(zhí)行文件來(lái)進(jìn)行反編譯,通過(guò)查看匯編語(yǔ)言代碼來(lái)尋找問(wèn)題解釋的蛛絲馬跡。不看不知道一看還真是有驚喜,加了if語(yǔ)句和加鎖等方式一樣全部會(huì)加上內(nèi)存寫屏障writeBarrier。具體如下:

未加if的匯編結(jié)果

0000000000499400 《main.main.func1》:499400: eb 00 jmp 499402 《main.main.func1+0x2》499402: eb 00 jmp 499404 《main.main.func1+0x4》499404: eb 00 jmp 499406

《main.main.func1+0x6》499406: eb fa jmp 499402 《main.main.func1+0x2》499408: cc int3499409: cc int349940a: cc int3 49940b: cc int349940c: cc int349940d: cc int3.。。省略0000000000499420 《type..eq.[2]interface {}》:499420: 64 48 8b 0c 25 f8 ff mov %fs:0xfffffffffffffff8,%rcx499427: ff ff499429: 48 3b 61 10 cmp 0x10(%rcx),%rsp 49942d: 0f 86 cf 00 00 00 jbe 499502 《type..eq.[2]interface {}+0xe2》499433: 48 83 ec 50 sub $0x50,%rsp

加了if或者鎖的匯編結(jié)果

wirteBarrier有點(diǎn)類似于文件操作中flush的作用,會(huì)強(qiáng)制把數(shù)據(jù)由緩存同步到內(nèi)存當(dāng)中去,因此我前文中所說(shuō)兩個(gè)變量其中一個(gè)加鎖,另一個(gè)結(jié)果也能不為0是因?yàn)樗麄冊(cè)谕痪彺嫘性蚪忉屢膊粚?duì),x和y并不是因?yàn)樵谕粋€(gè)緩存行所以才被一起同步回內(nèi)存的,而是由于wirteBarrier這個(gè)屏障所引入的。我們來(lái)看下面的代碼。

package main import (“fmt”//“sync/atomic”“time”) func main() {var x int32var y int32 slice := make([]int, 10, 10) z := 0 go func() {for { x++ y++for index, value := range slice { slice[index] = value + 1 }if z 》 0 { fmt.Println(“z is”, z) } } }() time.Sleep(time.Second) fmt.Println(“x=”, x) fmt.Println(“y=”, y) fmt.Println(“slice=”, slice)}

他的運(yùn)行結(jié)果是:

x= 86961625y= 86972610slice= [86978588 86979075 86979101 86979417 86979435 86979452 86979464 86979771 86979793 86979807]成功: 進(jìn)程退出代碼 0.

我造出來(lái)長(zhǎng)度為10整形切片,緩存行一般只有64BYTE,那么這個(gè)切片上面的數(shù)據(jù)是不可能在同一緩存行上的,通過(guò)這段代碼的執(zhí)行結(jié)果可以看到所有切換的值全部被更新了,因此我們可以了解writeBarrier這個(gè)內(nèi)存寫屏障的功能是將之前所有的數(shù)據(jù)全部強(qiáng)制回寫到內(nèi)存當(dāng)中。

我對(duì)于單核ECS中運(yùn)行的結(jié)果也是y=0的結(jié)果有了一定的認(rèn)識(shí),由于ECS虛擬機(jī)運(yùn)行的主體也是物理機(jī),而物理機(jī)肯定不是單核的,因此不執(zhí)行writeBarrier這個(gè)寫屏障語(yǔ)句,數(shù)據(jù)也無(wú)法刷回內(nèi)存,雖然程序運(yùn)行在單核虛擬機(jī)上,而虛擬機(jī)并不會(huì)把匯編指令再做包裝,這也就造成實(shí)際的執(zhí)行與多核環(huán)境沒(méi)有什么差別。

6if為什么會(huì)被如此安排

實(shí)在中If不但實(shí)際達(dá)到了內(nèi)存同步的效果,而且還效率更高,看起來(lái)非常適合這種沒(méi)有強(qiáng)制同步需要的使用場(chǎng)景。不過(guò)我們不禁要問(wèn)為什么編譯器要在出現(xiàn)if語(yǔ)句時(shí)顯式調(diào)用內(nèi)存屏障。個(gè)人猜測(cè)原因有兩個(gè),

if判斷使用真實(shí)值是隱含的前提:首先在進(jìn)行判斷時(shí),使用緩存中的數(shù)據(jù)可能會(huì)帶來(lái)顯而易見(jiàn)的問(wèn)題:因?yàn)樵谧雠袛鄷r(shí)程序員一般是要求用目前變量的實(shí)際值而不是緩存值來(lái)進(jìn)行的,這是一個(gè)隱含的前提,可能編譯器在優(yōu)化時(shí)考慮到了這一點(diǎn)。

指令流水線的原因:我們知道CPU的每個(gè)動(dòng)作都需要用晶體震蕩而觸發(fā),以加法ADD指令為例,想完成這個(gè)執(zhí)行指令需要取指、譯碼、取操作數(shù)、執(zhí)行以及取操作結(jié)果等若干步驟,而每個(gè)步驟都需要一次晶體震蕩才能推進(jìn),因此在流水線技術(shù)出現(xiàn)之前執(zhí)行一條指令至少需要5到6次晶體震蕩周期才能完成。如下圖:

為了縮短指令執(zhí)行的晶體震蕩周期,芯片設(shè)計(jì)人員參考了工廠流水線機(jī)制的提出了指令流水線的想法,由于取指、譯碼這些模塊其實(shí)在芯片內(nèi)部都是獨(dú)立的,完成可以在同一時(shí)刻并發(fā)執(zhí)行,那么只要將多條指令的不同步驟放在同一時(shí)刻執(zhí)行,比如指令1取指,指令2譯碼,指令3取操作數(shù)等等,就可以大幅提高CPU執(zhí)行效率:

以上圖流水線為例 ,在T5時(shí)刻之前指令流水線以每周期一條的速度不斷建立,在T5時(shí)代以后每個(gè)震蕩周期,都可以有一條指令取結(jié)果,平均每條指令就只需要一個(gè)震蕩周期就可以完成。這種流水線設(shè)計(jì)也就大幅提升了CPU的運(yùn)算速度。

但是if分支會(huì)造成流水線的停頓,也就是說(shuō)指令流水線系統(tǒng)無(wú)法確定在指令1執(zhí)行時(shí)確定指令7的具體情況。那么在if時(shí)加上writeBarrier這種耗時(shí)操作其實(shí)也就可以理解了,反正if也造拖慢執(zhí)行速度,那編譯器也就不在乎在此時(shí)加上另外的耗時(shí)操作了。

7Rust為什么令人羨慕

不過(guò)在看了一段時(shí)間的Rust后,我感覺(jué)Rust的優(yōu)勢(shì)是可以避免程序員犯很多錯(cuò)誤,而這其中所謂的錯(cuò)誤雖然看起來(lái)低級(jí),但是如果他們被隱藏在千萬(wàn)行代碼之中,那么排查起來(lái)真是相當(dāng)費(fèi)時(shí)費(fèi)力,由于已經(jīng)是所有權(quán)轉(zhuǎn)移了,因此變量的使用不太會(huì)出現(xiàn)像Go一樣的錯(cuò)誤情況,這點(diǎn)我們?cè)谏弦黄恼轮幸呀?jīng)有所論述了,而且我們來(lái)看以下代碼:

use std::thread;use std::mpsc;use std::Duration; fn main() {let (tx, rx) = mpsc::channel();let tx1 = mpsc::clone(&tx); //增加一個(gè)發(fā)送者tx1,需要clonelet tx2 =

mpsc::clone(&tx); //增加一個(gè)發(fā)送者tx2,需要clone thread::spawn(move || {let vals = vec?。跾tring::from(“I‘m”),String::from(“from”),String::from(“the”),String::from(“tx it self”), ]; for val in vals { tx.send(val).unwrap(); }}); thread::spawn(move || {let vals = vec!

[String::from(“I’m”),String::from(“from”),String::from(“the”),String::from(“tx1”), ]; for val in vals { tx1.send(val).unwrap(); }}); thread::spawn(move || {let vals = vec?。跾tring::from(“I‘m”),String::from(“from”),String::from(“the”),String::from(“tx2”), ]; for val in vals { tx2.send(val).unwrap(); }}); for received in rx { //一個(gè)通道一個(gè)接收者,接收若干個(gè)發(fā)送者的信息 println?。ā癎ot: {}”, received);} }

可見(jiàn)Rust中連管道的多路并發(fā)的管理使用都要通過(guò)clone的方式來(lái)安全傳遞信息,個(gè)人根本想不到用Rust編程怎么能出現(xiàn)像上面例子中Go造成的Bug,因此Rust的學(xué)習(xí)曲線雖然陡峭,但是感覺(jué)Rust程序包往往只掌握原生的框架就可以做得很好了,而不像Python、Java除了原生語(yǔ)言知識(shí)以外,還需要學(xué)習(xí)熟練運(yùn)用各種第三方的包。

馬超,CSDN博客專家,阿里云MVP、華為云MVP,華為2020年技術(shù)社區(qū)開(kāi)發(fā)者之星。

編輯:jq

聲明:本文內(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)投訴
  • BUG
    BUG
    +關(guān)注

    關(guān)注

    0

    文章

    156

    瀏覽量

    16026

原文標(biāo)題:遠(yuǎn)看像亂序執(zhí)行,近看是內(nèi)存屏障的 BUG 是如何解決的?

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

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    隔離屏障的概念以及工作電壓和測(cè)試電壓之間的區(qū)別

    電源中的電氣隔離不僅僅是關(guān)乎安全——它更是性能和可靠性的基石。本文將探討隔離屏障的概念以及工作電壓和測(cè)試電壓之間的區(qū)別。它還將討論標(biāo)準(zhǔn)為何重要?幫助工程師設(shè)計(jì)出滿足當(dāng)今嚴(yán)苛法規(guī)和應(yīng)用需求的穩(wěn)健系統(tǒng)。
    的頭像 發(fā)表于 07-08 15:29 ?211次閱讀

    allegro軟件走線命令下參數(shù)不顯示如何解

    在PCB設(shè)計(jì)中,走線命令是頻繁使用的功能之一。執(zhí)行走線命令后,通常會(huì)在Options面板中顯示線寬、層、角度等設(shè)置選項(xiàng),用于調(diào)整走線參數(shù)。然而,有時(shí)執(zhí)行走線命令后,Options面板中可能沒(méi)有顯示這些設(shè)置區(qū)域,如圖1所示,該如何解
    的頭像 發(fā)表于 06-05 09:30 ?504次閱讀
    allegro軟件走線命令下參數(shù)不顯示如<b class='flag-5'>何解</b>決

    STM32CubeIDE編譯設(shè)置是否有keil一樣有編譯后執(zhí)行Bat腳本的功能和設(shè)置?

    STM32CubeIDE編譯設(shè)置問(wèn)題,是否有keil一樣有編譯后執(zhí)行Bat腳本的功能和設(shè)置?或者有相關(guān)的腳本和插件?
    發(fā)表于 03-14 15:59

    DLP3010投影亂序何解決?

    目前我們用了兩組DLP3010 ,一樣的配置,一樣的固件,投影頻率不算太高,只是三組 LED燈的電流值調(diào)整的都是最大的2500, 現(xiàn)在其中一組3010出現(xiàn)了概率性的投影亂序的問(wèn)題,大概30組就會(huì)
    發(fā)表于 02-26 07:05

    Andes晶心科技推出AndesCore AX66亂序超純量多核處理器IP

    Andes晶心科技(Andes Technology)作為高效能、低功耗、32/64位RISC-V處理器核的領(lǐng)先供貨商及RISC-V國(guó)際組織的創(chuàng)始頂級(jí)會(huì)員,今日宣布推出支持RVA23規(guī)范的AndesCore AX66亂序超純量多核處理器IP。
    的頭像 發(fā)表于 01-23 11:05 ?862次閱讀

    FRED應(yīng)用:二階鬼分析

    一個(gè)長(zhǎng)的多階次的雜散光分析。本文介紹了一個(gè)腳本,可以在一個(gè)導(dǎo)入的序列設(shè)計(jì)中對(duì)初級(jí)鬼路徑進(jìn)行自動(dòng)分析。我們首先來(lái)討論合理地設(shè)置分析中導(dǎo)入的序列文件的過(guò)程,然后討論腳本的運(yùn)行以及執(zhí)行分析的過(guò)程。 指定
    發(fā)表于 01-10 08:55

    MQ消息亂序問(wèn)題解析與實(shí)戰(zhàn)解決方案

    作者:京東物流 劉浩 1. 背景 在分布式系統(tǒng)中,消息隊(duì)列(MQ)是實(shí)現(xiàn)系統(tǒng)解耦、異步通信的重要工具。然而,MQ消費(fèi)時(shí)出現(xiàn)的消息亂序問(wèn)題,經(jīng)常會(huì)對(duì)業(yè)務(wù)邏輯的正確執(zhí)行和系統(tǒng)穩(wěn)定性產(chǎn)生不良影響。本文將
    的頭像 發(fā)表于 12-06 09:46 ?644次閱讀

    虛擬內(nèi)存不足如何解決 虛擬內(nèi)存和物理內(nèi)存的區(qū)別

    虛擬內(nèi)存不足的解決方案 虛擬內(nèi)存不足是計(jì)算機(jī)用戶經(jīng)常遇到的問(wèn)題,尤其是在運(yùn)行大型軟件或多任務(wù)處理時(shí)。以下是一些解決虛擬內(nèi)存不足問(wèn)題的方法: 增加物理內(nèi)存(RAM) : 這是最直接的解決
    的頭像 發(fā)表于 12-04 09:14 ?1494次閱讀

    DDR內(nèi)存頻率對(duì)性能的影響

    DDR內(nèi)存頻率對(duì)性能的影響主要體現(xiàn)在以下幾個(gè)方面: 一、數(shù)據(jù)傳輸速度 內(nèi)存條的頻率(MHz)代表每秒的傳輸速度,即內(nèi)存每秒能夠執(zhí)行操作的次數(shù)。頻率越高,意味著數(shù)據(jù)傳輸速度越快。這有助于
    的頭像 發(fā)表于 11-20 14:25 ?3871次閱讀

    微處理器執(zhí)行指令的基本過(guò)程

    微處理器,作為現(xiàn)代計(jì)算機(jī)的核心部件,負(fù)責(zé)執(zhí)行存儲(chǔ)在內(nèi)存中的指令,完成各種計(jì)算和控制任務(wù)。指令的執(zhí)行過(guò)程不僅體現(xiàn)了微處理器的設(shè)計(jì)思想和架構(gòu)特點(diǎn),還直接影響到計(jì)算機(jī)的性能和效率。
    的頭像 發(fā)表于 10-05 15:07 ?1998次閱讀

    何解決工字電感噪音大的問(wèn)題

    電子發(fā)燒友網(wǎng)站提供《如何解決工字電感噪音大的問(wèn)題.docx》資料免費(fèi)下載
    發(fā)表于 09-04 11:46 ?0次下載

    何解決電感的漏感問(wèn)題

    電子發(fā)燒友網(wǎng)站提供《如何解決電感的漏感問(wèn)題.docx》資料免費(fèi)下載
    發(fā)表于 09-02 14:48 ?0次下載

    堆棧和內(nèi)存的基本知識(shí)

    本文主要聊聊關(guān)于堆棧的內(nèi)容。包括堆棧和內(nèi)存的基本知識(shí)。常見(jiàn)和堆棧相關(guān)的 bug,如棧溢出,內(nèi)存泄漏,堆內(nèi)存分配失敗等。后面介紹軟件中堆棧統(tǒng)計(jì)的重要性,以及如何使用工具工具軟件中堆棧使用
    的頭像 發(fā)表于 08-29 14:10 ?1048次閱讀
    堆棧和<b class='flag-5'>內(nèi)存</b>的基本知識(shí)

    stm32H7 HAL庫(kù)中存在的bug

    stm32H7 hal 庫(kù)里面的以太網(wǎng)代碼,坑了魚鷹很多次(不知道最新版是否已經(jīng)修復(fù)了這些bug),這里分享一篇網(wǎng)上的文章,因?yàn)轸~鷹也遇到過(guò),靠它解決了其中一個(gè)編譯優(yōu)化問(wèn)題,在此感謝作者。不過(guò)hal
    的頭像 發(fā)表于 08-12 17:37 ?2292次閱讀

    如何處理CPU亂序調(diào)度中的內(nèi)存數(shù)據(jù)依賴

    load和store指令首先發(fā)給reservation station ,然后發(fā)送到load單元或store 單元。
    的頭像 發(fā)表于 08-06 11:49 ?712次閱讀
    如何處理CPU<b class='flag-5'>亂序</b>調(diào)度中的<b class='flag-5'>內(nèi)存</b>數(shù)據(jù)依賴