指令層級平行與亂序執行

假相依(WAR 與 WAW)

想像兩位廚師很樂意平行工作,偏偏廚房只有一個標著「攪拌盆」的盆子,於是他們一直在等對方把盆子騰出來——不是因為誰需要對方的食物,而是因為他們在爭同一個容器。假相依正是如此:兩道指令被迫互相等待,不是因為真有資料在它們之間流動,只是因為它們碰巧重用了同一個暫存器名稱。各給一個盆子,衝突就消失了。

除了一種真的相依,還有兩種假的。真相依是寫後讀(RAW):指令 B 讀取指令 A 產生的值,所以 B 確實必須等。假的是:讀後寫(WAR,反相依)——B 要寫一個較早的 A 還需要讀的暫存器,所以 B 不能太早把它覆寫;以及寫後寫(WAW,輸出相依)——A 與 B 都寫同一個暫存器,而最後一次寫必須勝出。在 WAR 與 WAW 中,並沒有任何值真正從一道指令傳到另一道;唯一被共享的只是某個暫存器的名稱。這就是為何它們叫名稱相依,也是它們「假」的原因。

這對平行性影響極大。處理器只有幾十個架構暫存器名稱,所以繁忙的指令流會不斷重用它們,製造出假相依,把本來獨立的工作毫無必要地序列化。解方是暫存器更名:給每一次寫一個全新的實體暫存器,於是 WAR 與 WAW 相依直接消失,只留下演算法真正需要的 RAW 真相依。消除假相依,是亂序核心能找到遠超暫存器數量所暗示之平行性的最大原因之一。

(1) add x1 = x2 + x3;(2) add x2 = x4 + x5 在 x2 上有 WAR 危障——(2) 不能在 (1) 讀 x2 之前就寫它。把 (2) 的輸出更名到一個新的實體暫存器 p7,這兩道指令就完全獨立了。

WAR/WAW 是在爭一個名稱、不是爭資料——更名能讓它們消失。

別把假相依與 RAW 真相依搞混。只有 RAW 反映真實資料流、無法靠更名移除;WAR 與 WAW 只是暫存器名稱有限造成的人為產物,可以移除。

又稱
name dependencesanti-dependenceoutput dependence名稱相依反相依輸出相依