指令層級平行與亂序執行

動態排程(dynamic scheduling)

想像一家忙碌的小餐館,廚師並不堅持嚴格按訂單到達順序開始做菜。如果下一張單需要的食材還在烤箱裡,好廚師會先做一張較晚、但食材已經備在檯面上的單,讓廚房不停轉。動態排程就是硬體對指令做的這件事:在執行時、一道一道地,根據哪些輸入已就緒來決定接下來執行什麼——而不是盲目地照程式順序走。

具體來說,在靜態排程(循序)管線裡,如果指令 N 因等待一個慢值而停頓,排在它後面的每一道指令也跟著停頓,即使那些指令早就完全就緒。動態排程打破了這個壅塞。每道指令在一個緩衝區(保留站)裡等待,直到它的運算元抵達;一旦某道指令的輸入全部就緒、又有空閒的執行單元,它就執行——可能比一道仍在等待的較早指令更先執行。硬體自行追蹤所有在途的相依關係。Tomasulo 演算法是做這件事的經典配方,而動態排程正是讓亂序執行成為可能的東西。

它之所以重要,是因為最嚴重的停頓——快取未命中、慢速除法、長依賴鏈——都無法預測,只有執行時的決策能繞過它們。編譯器做靜態排程,無法得知某一次載入究竟會命中還是未命中。代價是複雜度:動態排程需要更名、緩衝與追蹤邏輯,這些都耗費面積與功耗。而它從不改變程式可見的答案——指令亂序執行,但循序提交,所以你觀察到的結果,就和一切照順序執行完全一樣。

指令 1「load x2 = [x1]」未命中快取(數百個週期)。指令 2「add x5 = x3 + x4」的輸入已就緒。動態排程的核心會現在就執行指令 2、而不是空轉,等載入終於回來後,再執行依賴指令 1 的那些指令。

誰現在就緒就先執行;讓停頓的那道指令稍後再趕上。

動態排程重排的是執行,而非程式的語意。它正是與循序提交搭配,才能在內部一通洗牌之後,仍讓架構狀態按原本的程式順序改變。

又稱
hardware scheduling硬體排程