上節課學習了指令集體系結構,其實是軟件和硬件間的接口,能夠分爲兩類,即精簡集和指令集。在複雜集的發展過程當中,逐漸吸取了精簡集的思想,雖然外部輸入的是複雜集體系接口,但會在內部分解爲微指令。函數
流水線技術的設計思想
- 單週期處理器:一個指令週期內只能完成一條指令的執行。單週期處理器的六個階段是串行工做,在某一時刻只有一部分硬件工做,硬件利用率低。
- 爲此,咱們採用了流水線技術,流水線既是一種思路,又是一種處理器處理結構,按照此思想設計出來的處理器結構稱爲流水線結構
以洗車爲例理解流水線的思想
洗車行至關於處理器,車至關於指令。性能
- 當洗車行只有一我的時,至關於單週期處理器
- 若三我的同時洗一輛車,至關於並行計算機的多核處理器。因爲在洗車過程當中有些工序相互干擾,如洗外邊的與洗裏邊的不能同時洗,因此花費時間並不會因爲投入人多而成倍減小。這種方式稱爲全並行
- 若採用了流水線做業,把洗車分爲三道工序,每人只負責一道工序。假設洗一輛車須要30分鐘,從微觀(單輛車)看,全並行至少須要10分鐘(三人互不干擾前提下),流水線責任至少須要30分鐘,還不算轉工序的時間;可是從宏觀(車絡繹不絕)看,只需10分鐘就一輛車。
- 因此,在處理器設計時,咱們採用了組合邏輯電路優化單週期處理器。組合邏輯電路分爲運算和儲存部分,時鐘週期不能小於運算與存儲的時間之和(300+20=320ps)。咱們採用流水線思想進一步優化,將運算部分均分爲三個階段,前一階段的輸出等於後一階段的輸入,並在每一階段後插入儲存部件,將上一級計算結果存儲到存儲部件中。當時鍾週期處於上升邊沿時,數據才能存儲到存儲部件並傳入下一階段中。
- 咱們以上邊所述的三階段流水線爲例,一條指令從執行到結束須要3個時鐘週期。儘管存儲器會有時間開銷(20ps),可是時鐘週期僅有120ps。這樣從微觀上看,一條指令執行須要360ps,多於300ps;可是當流水做業時,只需一個時鐘週期120ps就能夠完成一條指令,更快。並且全並行一個時間點上只有一部分部件工做,流水線則源源不斷工做,提升了硬件利用率。
- 所以流水線就是把一個時鐘週期只能執行一條指令,改成能夠多個時鐘週期執行一個指令。從而下降了時鐘週期,提升處理速度
流水線設計中遇到的挑戰
非均勻劃分
- 在實際處理器設計中,很難將處理器等分紅三份。由於每部分功能不一樣,沒法保證每部分完成功能消耗時間相同。而時鐘週期要保證每一個部件能正確完成結果的計算,就要以最慢的部分爲準。所以,提升最慢部分的速度對於提高總體性能最爲關鍵,提高快的部分是無論用的
流水線劃分的越細,是否就會收益越高
- 若各部分是均分的,性能確實會一直提升,可是性價比到後期會下降。如將三階段再細分爲6階段,中間須要插入5個儲存電路。從單週期到3階段,性能提高兩倍多;而從3階段到6階段卻只提高了一倍多。所以確實性能提高,但提高的會愈來愈慢。並且有效計算時間比會愈來愈低,存儲時間開銷佔比會愈來愈大(引入的存儲部件過多)。伴隨着儲存部件加的愈來愈多,成本提升,且對於單條指令的執行而言,時間變長。所以咱們要有trade-off折中概念:在成本和性能間找到一個平衡點。
- 若各部分不均分,則不必定性能提高提升。須要看進一步細分的是哪一個部分,若是是最慢的部分,性能會提升;若是是快的部分,性能不會提升。
通常流水線處理器包括5個階段:取址、譯碼、執行、訪存、寫回
- 與指令執行的6個階段不一樣,程序計數器的更新合併到了取址當中。由於取址和程序計數器的更新計算量很是小,就算合併到一塊兒,仍然比最慢的階段快。
- 執行、訪存是最慢的階段。由於執行的運算邏輯比較複雜,而訪存須要訪問內存,比較慢
- 後來,又對較爲複雜的執行和訪存階段作了進一步劃分,以縮短時鐘週期。
現代處理器設計中遇到的挑戰:理想狀況下指令的執行是很是罕見的
數據依賴問題
- 指令與指令間的數據有依賴。前邊指令運算獲得的值在後邊指令中會用到,這在單週期處理器中徹底沒有問題,但在多週期處理器中,若第一條指令還沒執行完,就到了第二條指令須要用到數據的階段,就會出現問題
- 針對這種問題,有兩種解決方式。一是在指令中插入延遲,如指令2的B階段要用到指令1的計算結果,就在b階段前插入一個氣泡,使處理器空一拍(全部指令都滯後一拍),先讓指令1算完。即經過插入氣泡,把某些並型指令串行化。可是在流水線中氣泡插多了性能會降低,而這種狀況又是很是常見的。
- 二是現代處理器經常使用的一種解決方式:亂序執行。在不影響流水線性能的前提下,打亂執行順序(但不改變最終邏輯)。對於指令順序的從新安排由硬件完成,將指令加載到指令池中,分析依賴關係,從新組織順序,再送入流水線,使其滿負荷運行。
控制依賴問題
- 流水線執行時,如有跳轉指令,後邊加載的指令是哪條很差說。只有等跳轉指令的結果計算出來,即跳轉指令執行完後,才知道執行哪條指令。若發生跳轉,本來後邊執行的指令就須要拋棄掉,引發改變的還須要復原。這也致使了流水線的清空,效率下降
- 目前主要採用分支預測方式解決這類問題,即先猜一下會不會跳轉,或者跳轉到那裏去。
- 動態分支預測:根據經驗猜想。如for循環第一次在某條指令跳到某個地址,後邊處理器到那條指令就會自動往那個地址跳,這樣最後只有兩次會出錯,一個是第一次,一個是最後一次。現代處理器中,動態分支預測技術成功率已經到達90%以上。聯想到rep:ret,rep是空指令,啥都不作,只是由於前邊有跳轉指令,兩個跳轉指令不能連續使用,所以用rep空指令隔開。這是因爲動態分支預測的侷限,不能預測連續的兩次跳轉目標。所以雖然插入空指令,但效率提高。儘管浪費了一個節拍,但避免了流水線清空
- 靜態分支預測:不是由處理器實現,而是由編譯器實現。如在gcc編譯器中就內置了 函數。根據可能性大小決定將哪一個分支放在跳轉指令緊後邊,使得下邊執行的指令就是邏輯執行的指令
- 也能夠採用條件數據傳輸解決,即先算出來
將來處理器的發展趨勢
- 超標量技術。將執行階段細分,設計了4個算數運算部件,還設計了一些數據加載、數據儲存部件。至關於將執行階段看作多個並行,前邊的取址階段是串行。這樣將執行階段並行,從宏觀上看縮短了單條指令的執行時間。可比做銀行先排隊取票,後多個窗口服務。即在單核處理器中,使局部某些指令實現全並行的效果