同時多執行緒(simultaneous multithreading, SMT)
/ S-M-T /
一顆寬的超純量核心像一間有八口爐的廚房,但單一份食譜很少同時需要全部八口——當一道菜在燉(一次快取未命中)時,好幾口爐就閒著。與其浪費它們,不如讓第二位廚師同時用那些空爐做另一份食譜。同時多執行緒(SMT)就是這件事:單一實體核心在同一週期內執行來自兩個(或更多)獨立執行緒的指令,填滿任何單一執行緒會留空的執行單元。
看一下這個家族會有幫助。粗粒度多執行緒只在發生大停頓時(如一次快取未命中)才切換到另一個執行緒,藉以隱藏長延遲。細粒度多執行緒則每個週期輪流切換執行緒,藉以隱藏較短的停頓。SMT 走得更遠:它不切換——它在同一個週期內就發射來自多個執行緒的指令,從每個執行緒就緒的指令中取材,把核心的發射槽填得更滿。在機制上,核心複製每執行緒的架構狀態(每個執行緒有自己的程式計數器與架構暫存器,透過更名映射到一個共享、更大的實體暫存器檔),但共用昂貴的執行單元、快取與預測器。對軟體而言,一顆 SMT 核心看起來像兩顆(或更多)邏輯處理器。Intel 把它的版本稱為超執行緒。
SMT 能廉價地提高吞吐量,因為它重用既有硬體去吸收單執行緒 ILP 填不滿的閒置槽與停頓週期——常見約 20–30% 的吞吐量增益,而面積代價不大。誠實的提醒既真實又不少:執行緒會爭奪共享的快取與執行單元,所以每執行緒效能可能下降,一顆核心上的兩個執行緒並不等於兩顆真核心;增益取決於工作負載、有時甚至是負的。而且由於 SMT 手足共用微架構資源(快取、預測器、埠),它們屢屢成為跨執行緒側通道與推測攻擊的途徑。
執行緒 A 因快取未命中停頓,留下大多數發射槽空著。有了 SMT,執行緒 B 就緒的指令這個週期就填進那些槽,於是核心的單元保持忙碌、總吞吐量上升——而 B 不必等 A 完成。
兩個執行緒在同一週期共用一顆核心的單元,吸收原本閒置的發射槽。
兩個 SMT 執行緒不等於兩顆核心:它們共用快取與執行單元,所以每執行緒的峰值速度可能下降、增益取決於工作負載。資源共用也使 SMT 手足成為反覆出現的側通道攻擊面。