【從零開始學習計算機科學】【從零開始學習計算機科學】計算機體系結構(二)指令級并行(ILP)
- ILP
- 流水線(pipeline)
- 流水線調度
- 循環展開和循環流水
- 循環展開。循環展開的具體步驟可以描述為,
- 軟件流水(循環流水)。我們可以通過流水線的思想處理循環的執行,即不需要這一次的循環體執行完畢,就可以開始下一次的循環體的執行。如果來自循環的迭代是獨立的,則可以通過從不同的迭代獲取指令,對于不同循環迭代的交聯指令可以重新組織循環,以便根據從原始循環的不同迭代選擇指令進行執行(類似 Tomasulo算法)
- 動態調度
- 記分牌(計分板)算法
- tomasulo算法
- 基于硬件的推測
- 指令多發射
- 通過存儲器體系結構和帶寬的優化來開發ILP
- ILP的局限性
- ILP總結
ILP
所有指令之間可能實現的通過重疊指令的執行過程成為指令級并行(ILP)。ILP通過重疊多個指令來提高性能利用執行指令所需的操作之間的并行性。即每秒鐘執行的指令數增加。而一個指令所需的時間不會更改,但是有可能會增加。ILP對高級(操作系統、程序)不可見。以下為一些常用的ILP技術。
流水線(pipeline)
流水線是實現指令級并行的有效措施之一。本書通過經典的MIPS五周期流水線CPU介紹pipeline技術。當然,流水線并不是只能用于指令級并行,流水線的核心思想可以擴展到許多應用場景,需要我們具體問題具體分析。
我們可以劃分指令的執行為以下 5 個經典的階段:
-
IF:指令提取
IF階段根據程序計數器(PC)從內存獲取當前指令。
通過向 PC 添加 4 個指令(因為每個指令是 4 個字節),按順序將 PC 更新到下一個指令的地址。 -
ID: 指令解碼 (帶寄存器提取)
解碼指令并讀取寄存器;在讀取寄存器時,對可能的分支執行相等性測試(提前分支判斷)。在需要的情況下,對指令的偏移字段進行符號擴展; 通過將符號擴展偏移量添加到遞增的 PC 來計算可能的分支目標地址。在實現了提前分支判斷的CPU中,如果條件測試為true,可以通過將目標地址存儲到 PC 中完成分支指令。 -
EX:執行
執行或有效地址計算,在載入-存儲體系結構中,無需指令同時計算數據地址并執行數據操作。 ALU 將處理兩種可能性之一。 -
MEM:內存訪問
訪存階段,對于load指令,ALU的輸出為要讀取的數據的地址,對于store指令,將寄存器的數據寫回到指定存儲器地址,ALU的輸出為要存入的數據的地址。 -
WB: (注冊) 回寫
寫回階段,將ALU計算的數據或load指令讀出的數據存入寄存器中。
流水線對單個任務的延遲沒有幫助,它有助于整個工作負載的吞吐量。流水線時鐘頻率速率受最慢管道階段限制,流水線的時鐘周期時間的最小值等于這五個階段關鍵路徑的延遲的最大值與寄存器延遲的和。流水線CPU的多個指令在同時運行,并且流水線的最大加速比等于流水線級數。流水線可以縮短每條指令的平均執行時間,這可認為是降低了CPI或時鐘周期時間。實際上,流水線并沒有縮短每條指令執行的總時間。反而,由于流水線開銷,指令的延遲實際上略有增加。
流水線的開銷主要表現在,第一,不平衡的管道階段,最慢的階段主導著總吞吐量。第二,流水線寄存器和時鐘偏斜,第三,寄存器的設置時間存在延遲。
實際中還存在時鐘偏斜,我們假設所有寄存器同時在時鐘邊緣觸發。在實際工作中,由于物理設計不完善,一些寄存器比其他人更早的到達時鐘邊緣。
并且,流水線中存在流水線冒險現象,其會阻止指令流的下一條指令執行。冒險會降低流水化帶來的加速比。
冒險通常會帶來流水線停頓,對于存在冒險的流水線的加速比,我們可以通過以下方式計算。加速比等于1除以1與每條指令的平均流水線停頓周期的和再乘流水線深度,流水線深度等于非流水化時鐘周期除以流水化時鐘周期。
冒險通常分為以下三類,1,結構冒險,即指令所需計算資源繁忙(例如,需要多個階段的指令,在這條指令執行的過程中,不能執行使用這個資源的其他指令)2,數據冒險,即指令之間的數據依賴關系,需要等待以前的指令來完成其數據讀/寫。3,控制冒險,執行流取決于以前的指令。比如分支跳轉指令。
對于不同的冒險,我們采用不同的方法來解決,但是解決這三種不同冒險的思路相似的。
對于結構冒險,其本質上是由于資源不足或者某一模塊流水化程度低導致的,為了避免結構冒險,最簡單方法解決方法便是流水線停頓,即等待上一條指令執行到消除冒險后再執行下一條指令。停頓通常稱為流水線氣泡,或稱為氣泡。對于只有一個寫端口的寄存器堆,在同一個時鐘周期內,若有兩條指令同時去寫寄存器堆,就會產生結構冒險,但是,一般來說,在同一個時鐘周期內,一條指令讀一條指令寫寄存器堆不會產生結構冒險。對于結構冒險的最有力的解決措施是添加硬件資源,可以(幾乎)消除結構危害。完全避免結構性危險是非常昂貴的,對于流水線功能單元成本更高(流水線式 FP ALU 成本高)。如果結構危險是罕見的,就忽略它。例如,如果 FP 操作很少,則只需使用非流水式 FP ALU。
對于數據冒險,數據冒險是由于指令之間的依賴導致的。通常情況下指令之間存在著依賴關系,即數據相關,我們可以把數據相關分為(真)數據相關,名稱相關和控制相關,對于存在依賴關系的兩條指令,其必須順序執行,不能進行重排序。對于真數據相關,我們可以通過合適的調度盡可能地在保持依賴關系的同時減少冒險的發生,對于名稱相關,我們可以通過寄存器重命名解決。數據冒險一定發生于存在依賴關系的指令之間,但是存在依賴關系的指令執行時不一定發生數據冒險。對于控制相關,其主要表現為控制相關的指令受到其對應的控制指令(一般是分支指令)控制,只有在應當執行時去執行。對于控制相關,我們可以通過推測來實現存在控制相關的指令的調度。
數據冒險按數據依賴關系劃分可以分成以下三類。
1,寫后讀(RAW)。寫后讀冒險是由于在寫指令i執行前讀指令j試圖讀取相應的寄存器。
2,讀后寫(WAR)。WAR冒險是由于讀指令i執行前寫指令j試圖寫入相應的寄存器。
3,寫后寫(WAW)依賴。WAR冒險是由于寫指令i執行前寫指令j試圖寫入相應的寄存器。
對于RAW冒險,其來源于真數據依賴,而對于WAR和WAW冒險,其來源于名稱相關,因此,WAR和WAW冒險可以通過寄存器換名解決。
一般來說,對于數據冒險,我們可以通過旁路(數據前推或短路)和流水線暫停實現數據冒險的解決。旁路技術主要是通過將計算結果通過流水線寄存器轉發到當前執行的其他指令之中,其他指令可以通過流水線寄存器獲取存在數據依賴的指令的執行結果而不必要等其執行完畢后才獲取。比如,對于