我叫阿Q,是CPU一號車間裡的員工,我所在的這個CPU足足有8個核,就有8個車間,幹起活來槓槓滴。
我們CPU的任務就是執行程式設計師編寫的程式,只不過程式設計師編寫的是高階語言程式碼,而我們執行的是這些程式碼被編譯器編譯之後的機器指令。
那一天,我正在忙活著···
「阿Q,工作時間你怎麼在摸魚啊!」,領導突然到訪,嚇得我一哆嗦。
「領導,我正在執行的這條指令,需要從記憶體讀取資料,這您是知道的,記憶體那傢伙可慢了,所以我只好等著,這可不是摸魚哦···」,我小心地解釋到。
領導眉頭緊鎖,指著一片電路問道:「這些是做什麼的,怎麼沒在工作?」
「那是讀取指令的電路」
「旁邊那些呢」
「那是指令譯碼的電路,我手裡這條指令還沒執行完,現在還輪不到它們工作」
「反正也是閒著,就不能提前處理下一條指令嗎?」,領導問道。
「不行啊,我們一直都是一條指令處理完成才處理下一條指令」
「這些電路單元閒著有點浪費啊,可惜了」,領導嘴裡唸叨著離開了我們一號車間,留下不知所措的我呆在原地。
沒過幾天,領導找我們幾個車間的代表開了個會。
會上,領導問道:「各位,咱們執行指令的效率能不能提一提,競爭對手快追上我們了」
「這怎麼提啊,我們幹活夠賣力的了」
「是啊,也沒有划水偷懶」
各車間代表七嘴八舌地說到。
「還說沒有划水?我最近去各車間巡視,經常發現有人摸魚」
一聽這話,大家都沉默,我也羞愧地低下了頭。
領導接著說道:「我在想啊,咱們現在執行指令的過程存在不少的資源浪費,大家能不能別等一條指令執行完再執行下一條,而是提前執行下一條」
這話一出,在場各車間的代表都滿臉問號。我們平時都是一條一條地執行指令,怎麼還能提前執行後面的指令呢,這簡直有點不可思議。
見大家一臉茫然,領導接著說道:「咱們現在執行指令的過程其實是分了好幾個步驟的,不同的步驟需要用到的電路裝置基本上是不一樣的,在執行後面步驟的同時,前面步驟所用到的電路就可以騰出來用於處理後面的指令了」
就在我還有些似懂非懂時,二號車間小虎站起來說道:「我明白了!」
領導露出了滿意的笑容,問道:「說說看,你明白什麼了」
小虎轉身來到一旁的畫板上,畫了一張圖:
「大家請看,我們平時執行指令,差不多四個主要的步驟:讀取指令、指令譯碼、指令執行、資料回寫。在第一條指令進入指令譯碼的步驟時,負責讀取指令的電路模組就閒下來了,這時可以用來讀取下一條指令,提前節省了時間。等到第一條指令進入執行的步驟時,指令譯碼的電路就能用來處理第二條指令,而讀取指令的電路就能用來讀取第三條指令,以此類推!」,小虎得意的說到。
「妙啊,妙啊!」,我也忍不住稱讚道:「整個過程就像一條流水線一樣,一環扣一環!這效率肯定能提升不少」
「流水線?這個名字好,要不咱們就把這項技術叫做指令流水線吧!」,領導說到。
不久,咱們CPU各個車間就開始正式推行這項技術,把原來執行指令的過程流水線化。
在我們一號車間又增加了一些人手:負責指令讀取的小A、負責指令譯碼的小胖,負責結果回寫的老K,至於我嘛,就負責具體的指令執行。
用上了流水線之後,我們CPU的工作效能一下有了非常明顯的提升,甩開了競爭對手一大截,領導高興壞了。
但還沒高興太久,不知道誰走漏了訊息,競爭對手CPU們也知道了這項技術,也用上了指令流水線,我們的差距又一次縮小了。
領導又一次召開會議。
「現在該怎麼辦?大家想想辦法啊」
會場一度陷入了沉默,過了一會兒,六號車間的代表小六才站起來發言:「領導,我有一個辦法」
「什麼辦法?」
小六潤了潤嗓子說道:「我先問大家一個問題,在我們沒有使用指令流水線技術的時候,假設執行一條指令需要4個步驟,每個步驟需要1ns,那執行完一條指令總共需要多少時間?4條指令全部執行完又需要多少時間呢?」
「一個步驟1ns,一條指令總共4個步驟就是4ns,4條指令就是16ns,這也太簡單了吧」,二號車間小虎說到。
「沒錯,那用上流水線以後呢?」
「讓我想想,用了流水線技術以後,從第4ns開始,每過1ns就會有1條指令從流水線上完成,完成上面4條指令,總共只需要7ns,比原來省了一半的時間。」
「說的沒錯,大家發現沒有,如果我們把執行步驟拆的再細一些,每個小步驟需要的時間更短一些,這樣流水線的深度就會更深一些,流水線中容納的指令也就越多,效能就會變得更高。」,小六激動的說到。
領導也聽得有些糊塗,打斷問道:「等等,你慢一點,我沒太明白」
小六繼續說道:「比如從現在的4個步驟,拆成8個更小的步驟,每個小步驟需要的時間減半為0.5ns,這樣一來,流水線跑起來後,每隔0.5ns的時間就會有一條指令完成,比4個步驟的情況更快了!「
「妙啊!妙啊!」,領導忍不住鼓掌說道:「就這麼幹」
我總覺得哪裡不太對勁,卻一時也說不上來。
回去之後,我們就進行升級改造,將現在的四級流水線,改造成八級。
你還別說,效果還真是立竿見影,將指令執行過程拆分得更細以後,流水線中容納的指令數變得更多了,進一步減少了CPU電路資源的浪費,執行效能比以前更強了。
但沒過多久,競爭對手CPU也把流水線級數增加了,而且比我們的還多,這可急壞了領導。
沒有辦法,我們也只好再一次提升流水線級數來應對。
就這樣雙方你來我往,我們玩起了流水線級數大戰,最瘋狂的時候,我們把流水線級數做到了三十級。
終於,我們搞出了事情。
我們把一條指令的執行過程拆分的越來越細,雖然是提高了資源的利用率,但每個小步驟之間都需要做好交接,就需要增加很多額外的電路裝置。
步驟之間交接不僅有額外的時間開銷,增加的電路裝置也會產生額外的功耗。
流水線級數到了一定深度後,發現效能沒有增加反而下降了,而且功耗越來越大,風扇都要瘋狂轉起來給我們降溫。
看來這流水線級數也不是越多越好啊!我們又主動降低了流水線級數,在效能和功耗上選擇了一個平衡點。
不僅如此,我們在使用指令流水線的過程中,也漸漸地發現了一些其他問題。
有時候,我執行到一些指令,需要從記憶體讀取資料到暫存器中。不巧的是,負責讀取指令的小A也準備從記憶體中讀取後面的指令,這同一時間咱倆都要存取記憶體,都要使用訪存電路,這下尷尬了,搞得流水線只好停頓下來等待,等我用完了小A再用,白白浪費了時間。
還有的時候,我執行到一些指令,所需要的資料來自於前一條指令計算的結果,可流水線中前一條指令還沒有結束,結果還拿不到,流水線只好又停頓下來等待。
這都還不算啥,更要命的是,遇到了有分支的時候,根本不知道要去把哪個分支的指令加入流水線中處理。
於是,我們把這些問題都集中反饋了上去,後來我發現不僅僅是我們車間,其他車間也遇到了這些問題。
大家把這些問題叫做流水線裡的冒險,還給這三種問題分別取了三個名字:
- 結構冒險 :流水線中出現硬體資源競爭
- 資料冒險:流水線中後面的指令需要等待前面指令完成資料的讀寫
- 控制冒險:流水線需要根據前面指令的執行結果來決定下一步去哪執行
一時之間大家都沒有什麼好的辦法,遇到這些問題就只好讓流水線停頓下來等待,等待前面的指令完成,再繼續工作。
但不斷追求效能提升的領導,肯定不會放任這幾個問題不管,又會想出什麼樣的應對辦法呢?
【完】
上面的故事,出自我的新書 《趣話計算機底層技術》 ,如果覺得還不錯的話,歡迎大家衝一波呀~