👆如果您希望可以時常見面,歡迎標星🌟收藏哦~
GPU 是加速高效能計算(HPC)工作負載的熱門平臺,廣泛應用於人工智慧和科學模擬等領域。然而,學術界的大多數微架構研究仍基於 15 年前的 GPU 核心流水線設計。
本文透過逆向工程剖析了現代英偉達 GPU 核心,揭示了其設計的關鍵方面,並解釋了 GPU 如何利用硬體-編譯器協同技術,在執行過程中由編譯器引導硬體工作。具體而言,研究揭示了指令發射邏輯的工作機制,包括髮射排程器的策略、暫存器檔案及其相關快取的結構,以及記憶體流水線的多個特性。此外,分析了基於流緩衝區的簡單指令預取器如何與現代英偉達 GPU 相適配並可能被採用。進一步研究了暫存器檔案快取和暫存器檔案讀埠數量對模擬準確性和效能的影響。
透過對這些新發現的微架構細節進行建模,與之前的先進模擬器相比,我們的模型在執行週期的平均絕對百分比誤差(MAPE)降低了18.24%,與實際硬體(英偉達RTX A6000)相比,平均絕對百分比誤差為13.98%。此外,我們證明了該新模型適用於其他英偉達架構,如圖靈架構。
最後,研究表明,現代英偉達 GPU 中基於軟體的依賴管理機制在效能和麵積方面優於傳統的基於計分板的硬體機制。
引言
近年來,GPU 除了在圖形處理領域應用廣泛外,在執行通用工作負載方面也備受青睞。GPU 的架構提供了大規模並行處理能力,許多現代應用,如生物資訊學、物理學和化學等領域,都可以利用這一特性。如今,GPU 已成為加速現代機器學習工作負載的主要選擇,這些工作負載對記憶體頻寬和計算能力有著極高的要求。近年來,GPU 的微架構、互連技術(NVLink)和通訊框架(NCCL)都取得了重大創新。這些進展推動了大型語言模型的推理和訓練,而這往往需要配備數千個 GPU 的叢集。
然而,關於現代商用 GPU 微架構設計的公開資訊較少,目前學術界的研究大多以 2006 年推出的特斯拉微架構為基準。但自特斯拉架構以來,GPU 架構已經發生了顯著變化,因此基於該架構的模型可能會導致研究結果出現偏差。本研究旨在揭示現代英偉達 GPU 架構中各個元件的不同特性和細節,以提高學術微架構模型的準確性。本文所解釋的模型和細節有助於研究人員更好地識別改進未來 GPU 的挑戰和機遇。總之,本文做出了以下貢獻:
-
描述了指令發射階段的操作,包括依賴處理、執行緒束(warp)的就緒條件以及發射排程器的策略。
-
描述了取指階段及其排程器的合理操作,該排程器與發射階段協同工作。
-
提供了暫存器檔案的重要細節,並解釋了暫存器檔案快取的行為。此外,研究表明現代英偉達 GPU 不使用運算元收集階段或收集單元。
-
揭示了記憶體流水線元件的多個細節。
-
重新設計了 Accel-sim 模擬器中使用的 SM / 核心模型,並將本文揭示的所有細節整合到該模型中。
-
使用實際硬體對新模型進行驗證,並與 Accel-sim 模擬器進行比較。我們的新模型在與英偉達 RTX A6000(安培架構)實際硬體對比時,執行週期的平均絕對百分比誤差(MAPE)為 13.98%,比之前的模擬器模型提高了 18.24%。
-
證明了基於簡單流緩衝區的指令預取器在效能準確性方面表現出色,其效能與完美指令快取相近。
-
展示了暫存器檔案快取和暫存器檔案讀埠數量對模擬準確性和效能的影響。
-
比較了本文揭示的依賴管理系統與傳統計分板在效能、面積和模擬準確性方面的差異。結果表明,這種新穎的軟硬體協同設計比傳統計分板在處理依賴關係方面更高效。
-
展示了該模型對其他英偉達架構(如圖靈架構)的適用性。
本文的其餘部分組織如下:第 2 節介紹了這項工作的背景和動機;第 3 節解釋了我們採用的逆向工程方法;第 4 節描述了現代英偉達 GPU 架構中的控制位及其詳細行為;第 5 節介紹了這些 GPU 的核心微架構;第 6 節描述了我們在模擬器中建模的特性;第 7 節評估了我們的模型與實際硬體相比的準確性,並將其與 Accel-sim 框架模擬器進行比較,分析了指令預取流緩衝區的影響,研究了暫存器檔案快取和暫存器檔案讀埠數量的影響,比較了不同的依賴管理機制,並討論了該模型對其他英偉達架構的適用性;第 8 節回顧了先前的相關工作;最後,第 9 節總結了這項工作的主要成果。
背景和動機
學術界的大多數 GPU 微架構研究依賴於 GPGPU-Sim 模擬器採用的微架構。最近,該模擬器進行了更新,納入了從 Volta 架構開始的子核心(英偉達術語中的處理塊)方法。圖 1 展示了該模擬器中建模的架構框圖。可以看到,它由四個子核心和一些共享元件組成,如 L1 指令快取、L1 資料快取、共享記憶體和紋理單元。

在這個 GPU 流水線的取指階段,迴圈排程器會選擇下一條指令位於 L1 指令快取中且指令緩衝區有空閒槽位的執行緒束。這些緩衝區專用於每個執行緒束,用於儲存執行緒束中取指和解碼後的連續指令。指令會一直留在這個緩衝區中,直到準備好並被選中發射。
在發射階段, GTO排程器會選擇一個執行緒束進行指令發射,條件是該執行緒束不在等待屏障,並且其最老的指令與流水線中其他正在執行的指令沒有資料依賴關係。先前的研究假設每個執行緒束有兩個計分板來檢查資料依賴。第一個計分板標記對暫存器的待寫操作,以跟蹤寫後寫(WAW)和寫後讀(RAW)依賴。只有當指令的所有運算元在這個計分板中都被清除時,該指令才能被髮射。第二個計分板統計暫存器的活躍消費者數量,以防止讀後寫(WAR)危害。第二個計分板是必要的,因為儘管指令按順序發射,但它們的運算元可能會亂序獲取,這種情況會發生在可變延遲指令(如記憶體指令)上。這些指令在發射後會被排隊,並且可能在較年輕的算術指令寫入結果後讀取其源運算元,如果前者的源運算元與後者的目的運算元相同,就會導致讀後寫危害。
一旦指令被髮射,它會被放置在一個收集單元(CU)中,等待直到獲取到所有源暫存器運算元。每個子核心都有一個私有的暫存器檔案,包含多個儲存體,每個儲存體有幾個埠,這樣可以在單個週期內以較低成本進行多次訪問。仲裁器負責處理對同一儲存體的多個請求可能產生的衝突。當指令的所有源運算元都在收集單元中時,該指令會移動到分發階段,在這個階段,它會被分發到合適的執行單元(如記憶體單元、單精度單元、特殊功能單元),執行單元的延遲取決於單元型別和指令。一旦指令到達寫回階段,結果會被寫入暫存器檔案。
Accel-sim 中建模的 GPU 微架構類似於基於 2006 年釋出的特斯拉架構的英偉達 GPU,並更新了一些現代特性,主要是子核心模型和類似於 Volta 架構的採用 IPOLY 索引的扇區快取。然而,它缺少現代英偉達 GPU 中存在的一些重要元件,如 L0 指令快取和統一暫存器檔案。此外,子核心的一些主要元件,如發射邏輯、暫存器檔案或暫存器檔案快取等,並沒有更新以反映當前的設計。
這項工作旨在對現代英偉達 GPU 核心的微架構進行逆向工程,並更新 Accel-sim 模擬器以融入新發現的特性。這將使更新後的 Accel-sim 模擬器的使用者能夠以更接近行業在商業設計中證明成功的基線開始工作,從而使他們的工作更具相關性。
逆向工程方法
本節解釋了我們用於發現英偉達安培架構 GPU 核心(SMs)微架構的研究方法。
我們的方法基於編寫包含少量指令的小型微基準測試,並測量特定短指令序列的執行時間。透過在程式碼區域周圍使用指令將 GPU 的時鐘計數器儲存到暫存器中,並將其儲存在主記憶體中以供後續後處理,從而獲得經過的週期數。評估的指令序列通常由手寫的 SASS 指令(及其控制位)組成。根據測試的不同,我們會視覺化記錄的週期數,以確認或反駁關於控制位語義或微架構中特定特性的假設。
下面給出兩個示例來說明這種方法:

雖然英偉達沒有官方工具直接編寫 SASS 程式碼(英偉達組合語言),但各種第三方工具允許程式設計師重新排列和修改彙編指令(包括控制位)。例如,當編譯器生成的程式碼不是最優時,這些工具可用於最佳化關鍵核心的效能。MaxAS 是第一個用於修改 SASS 二進位制檔案的工具,隨後,針對 Kepler 架構開發了其他工具,如 KeplerAS。然後,TuringAS 和 CUAssembler 出現,以支援更新的架構。由於其靈活性、可擴充套件性以及對最新硬體的支援,我們決定使用 CUAssembler。
現代英偉達 GPU 架構中的控制位
現代英偉達 GPU 架構的指令集架構(ISA)包含控制位和編譯器提供的用於確保正確性的資訊。與先前工作中透過在執行時跟蹤暫存器讀寫來檢查資料依賴的 GPU 架構不同,這些 GPU 架構依賴編譯器來處理暫存器資料依賴。為此,所有彙編指令都包含一些控制位,除了提高效能和降低能耗外,還用於正確管理依賴關係。
下面描述每個指令中包含的這些控制位的行為。解釋基於一些文件,但這些文件通常含糊不清或不完整,因此我們使用第 3 節中描述的方法來揭示這些控制位的語義,並驗證它們是否如以下所述那樣工作。
子核心每個週期可以發射一條指令。預設情況下,如果執行緒束程式順序中最老的指令已準備好,發射排程器會嘗試發射該執行緒束的指令。編譯器使用控制位指示指令何時準備好發射。如果前一個週期發射指令的執行緒束中最老的指令未準備好,發射邏輯會根據 5.1 小節中描述的策略從另一個執行緒束中選擇一條指令。
為了處理固定延遲指令的生產者-消費者依賴關係,每個執行緒束都有一個計數器,稱為停頓計數器(Stall counter)。如果這個計數器不為零,該執行緒束就不是發射指令的候選者。編譯器會根據產生指令的延遲減去生產者和第一個消費者之間的指令數量來設定這個計數器。所有這些每個執行緒束的停頓計數器每個週期減 1,直到達到 0。發射邏輯只會檢查這個計數器,並且在其值為 0 之前不會考慮發射同一執行緒束的另一條指令。
例如,一條延遲為 4 個週期且其第一個消費者是下一條指令的加法指令,會在停頓計數器中編碼為 4。使用第 3 節中解釋的方法,我們已經驗證,如果停頓計數器設定不正確,程式的結果將是錯誤的,因為硬體不會檢查 RAW 危害,而是簡單地依賴這些由編譯器設定的計數器。此外,這種機制在面積和能量佈線方面有優勢。要知道,與傳統計分板方法不同,固定延遲單元到依賴處理元件的佈線是不需要的。
另一個控制位稱為 Yield,用於指示硬體在下一個週期不應發射同一執行緒束的指令。如果子核心的其他執行緒束在下一個週期都未準備好,則不會發射任何指令。
每個指令都會設定停頓計數器和 Yield 位。如果停頓計數器大於 1,執行緒束將至少停頓一個週期,在這種情況下,無論 Yield 位是否設定都會停頓。
另一方面,一些指令(如記憶體指令、特殊功能指令)具有可變延遲,編譯器不知道它們的執行時間。因此,編譯器無法透過停頓計數器來處理這些危害。這些危害透過依賴計數器位來解決。每個執行緒束有六個特殊暫存器來儲存這些計數器,稱為 SBx,其中 x 的取值範圍為 [0 – 5]。每個計數器最多可以計數到 63。
當一個執行緒束開始時,這些計數器被初始化為 0。為了處理生產者 – 消費者依賴,生產者在發射後增加一個特定的計數器,並在寫回時減少它。消費者指令被指示等待,直到這個計數器為 0。
對於 WAR 危害,機制類似,唯一的區別是計數器在指令讀取其源運算元後減少,而不是在寫回時減少。
在每個指令中,有一些控制位用於指示最多兩個在發射時增加的計數器。其中一個計數器將在寫回時減少(用於處理 RAW 和 WAW 依賴),另一個在暫存器讀取時減少(用於處理 WAR 依賴)。為此,每個指令有兩個 3 位的欄位來指示這兩個計數器。此外,每個指令有一個 6 位的掩碼,用於指示它必須檢查哪些依賴計數器以確定是否準備好發射。注意,一條指令最多可以檢查所有六個計數器。
考慮到如果一條指令有多個源運算元,且其生產者具有可變延遲,所有這些生產者可以使用相同的依賴計數器而不會損失任何並行性。需要注意的是,在有超過六個具有不同可變延遲生產者的消費者指令的場景中,這種機制可能會遇到並行性限制。在這種情況下,編譯器必須在兩種選擇中做出決定來管理這種情況:1)將更多指令分組在同一個依賴計數器下;2)以不同方式重新排序指令。
依賴計數器的增加是在發射生產者指令後的週期進行的,因此直到一個週期後才會生效。因此,如果消費者是下一條指令,生產者必須將停頓計數器設定為 2,以避免在下一個週期發射消費者指令。
處理具有可變延遲生產者的依賴關係的示例可以在圖 2 中找到。這段程式碼展示了四條指令(三條載入指令和一條加法指令)及其相關編碼。由於加法指令與載入指令(可變延遲指令)存在依賴關係,因此使用依賴計數器來防止資料危害。地址為 PC 0x80 的指令與地址為 0x50 和 0x60 的指令存在 RAW 依賴關係。因此,SB3 在指令 0x50 和 0x60 發射時增加,並在寫回時減少。另一方面,加法指令與地址為 0x60 和 0x70 的指令存在 WAR 依賴關係。因此,SB0 在指令 0x60 和 0x70 發射時增加,並在讀取它們各自的暫存器源運算元後減少。最後,加法指令的依賴計數器掩碼編碼表示在發射之前,SB0 和 SB3 必須為 0。注意,指令 0x70 還使用 SB4 來控制與未來指令的 RAW/WAR 危害,但指令 0x80 不需要等待這個依賴計數器,因為它與該載入指令沒有任何依賴關係。在讀取源運算元後清除 WAR 依賴是一項重要的最佳化,因為源運算元有時會比結果產生的時間早得多被讀取,特別是對於記憶體指令。例如,在這個例子中,指令 0x80 會等待直到指令 0x70 讀取 R2 以清除這個 WAR 依賴,而不是等待直到指令 0x70 執行寫回操作,後者可能會在數百個週期後發生。
檢查這些計數器是否就緒的另一種方法是透過 DEPBAR.LE 指令。例如,DEPBAR.LE SB1, 0x3, {4,3,2} 要求依賴計數器 SB1 的值小於或等於 3 才能繼續執行。最後一個引數([, {4,3,2}])是可選的,如果使用,該指令在指定 ID(在這個例子中為 4、3、2)的依賴計數器值等於 0 之前不能發射。
DEPBAR.LE 在某些特定場景中特別有用。例如,當一個消費者需要等待一系列 N 個按順序寫回的可變延遲指令(例如帶有 STRONG.SM 修飾符的記憶體指令)中的前 M 條指令時,它允許對這一系列指令使用相同的依賴計數器。使用 DEPBAR.LE 並將其引數設定為 N-M 會使這條指令等待序列中的前 M 條指令。另一個例子是重用相同的依賴計數器來保護 RAW/WAW 和 WAR 危害。如果一條指令對兩種型別的危害都使用相同的依賴計數器,由於 WAR 危害比 RAW/WAW 危害解決得更早,後續的 DEPBAR.LE SBx, 0x1 會等待直到 WAR 危害得到解決,然後允許執行緒束繼續執行。後續使用其結果的指令需要等待直到這個依賴計數器變為 0,這意味著結果已經被寫入。
此外,GPU採用暫存器檔案快取(register file cache)來降低能耗並減少暫存器檔案讀埠的爭用。該結構透過軟體管理:每條指令的源運算元包含一個控制位(稱為reuse位),用於指示硬體是否快取該暫存器的內容。關於暫存器檔案快取組織架構的更多細節詳見第5.3.1節。
最後,需要說明的是,雖然本文聚焦NVIDIA架構,但透過研究AMD GPU指令集文件可以發現,AMD同樣採用硬體-軟體協同設計來管理依賴關係並提升效能。與NVIDIA的DEPBAR.LE指令類似,AMD使用waitcnt指令——根據架構版本不同,每個wavefront(相當於warp)配備3至4個專用計數器,每個計數器對應特定指令型別,用於防範相關指令造成的資料衝突。AMD不允許常規指令透過控制位直接等待計數器歸零,而必須顯式插入waitcnt指令,這會增加指令總數。這種設計雖然降低了解碼開銷,卻導致整體指令數量上升。相比之下,NVIDIA的方案具有兩大優勢:1) 每個warp可用的計數器數量多出2個(共6個);2) 計數器不與特定指令型別繫結,從而支援同一指令型別內更並行的依賴鏈管理。值得注意的是,AMD在RDNA 3/3.5架構中引入了DELAY_ALU指令來緩解ALU指令依賴導致的流水線停頓,其優勢在於無需編譯器介入即可避免ALU指令的資料衝突。而NVIDIA則依賴編譯器為固定延遲指令正確設定Stall計數器,這種方式雖減少了指令數量,但增加了解碼開銷。
GPU 核心微架構
在本節中,我們使用第 3 節中解釋的方法,描述我們對現代商用英偉達 GPU 核心微架構的研究發現。圖 3 展示了 GPU 核心微架構的主要元件。下面,我們將詳細描述指令發射排程器、前端、暫存器檔案和記憶體流水線的微架構。
1
指令發射排程器
在本小節中,我們剖析現代英偉達 GPU 的指令發射排程器。首先,在(1)小節中描述每個週期中哪些執行緒束被視為指令發射的候選者。然後,在(2)小節中介紹選擇策略。
(1)執行緒束就緒條件
在給定週期內,若滿足某些條件,執行緒束會被視為發射其最老指令的候選者。其中一些條件取決於同一執行緒束的先前指令,而另一些則依賴於核心的全域性狀態。
一個顯而易見的條件是指令緩衝區中存在有效指令。另一個條件是執行緒束的最老指令與同一執行緒束中尚未完成的較老指令之間不能有任何資料依賴風險。指令之間的依賴關係透過第 4 節中描述的控制位,藉助軟體支援來處理。
此外,對於固定延遲指令,只有在確保指令發射後執行所需的所有資源都可用的情況下,執行緒束才會被視為在給定週期內發射其最老指令的候選者。
這些資源之一是執行單元。執行單元有一個輸入鎖存器,當指令到達執行階段時,該鎖存器必須為空。如果執行單元的寬度僅為半個執行緒束,此鎖存器會被佔用兩個週期;若為完整執行緒束的寬度,則佔用一個週期。
對於在常量快取中有源運算元的指令,在發射階段進行標籤查詢。當所選執行緒束的最老指令需要從常量快取中獲取運算元,而該運算元不在快取中時,排程器會暫停指令發射,直到快取缺失問題得到解決。然而,如果在四個週期後快取缺失仍未得到處理,排程器會切換到另一個執行緒束(具有就緒指令的最年輕執行緒束)。


至於暫存器檔案讀埠的可用性,指令發射排程器並不知道被評估的指令在後續週期中是否有足夠的埠用於讀取而不會出現停頓。我們在觀察到如果刪除清單 1 中最後一條 FFMA 指令和最後一條 CLOCK 指令之間的 NOP 指令,程式碼中的衝突不會導致第二條 CLOCK 指令的發射停頓後,得出了這一結論。我們進行了大量實驗來揭示指令發射和執行之間的流水線結構,但未能找到一個完美符合所有實驗結果的模型。不過,下面描述的模型幾乎適用於所有情況,所以我們採用這個模型。在這個模型中,固定延遲指令在指令發射階段和讀取源運算元的階段之間有兩個中間階段。第一個階段稱為控制階段,固定延遲指令和可變延遲指令都會經過這個階段,其職責是增加依賴計數器,或者在需要時讀取時鐘計數器的值。我們的實驗證實,這導致增加依賴計數器的指令和等待該依賴計數器歸零的指令之間至少需要一個週期,才能使增加的計數生效,所以兩條連續的指令不能使用依賴計數器來避免資料依賴風險,除非第一條指令設定了 Yield 位或停頓計數器大於 1。
第二個階段僅存在於固定延遲指令中。在這個階段,檢查暫存器檔案讀埠的可用性,指令會在這個階段停頓,直到確保其可以繼續執行而不會發生暫存器檔案埠衝突。我們將這個階段稱為分配階段。有關暫存器檔案讀寫流水線及其快取的更多詳細資訊,請參見 5.3 小節。可變延遲指令(例如記憶體指令)在經過控制階段後(不經過分配階段)會直接進入一個佇列。當佇列中的指令確保不會發生任何衝突時,它們才被允許進入暫存器檔案讀取流水線。固定延遲指令在分配暫存器檔案埠時優先於可變延遲指令,因為如上文所述,依賴關係由軟體處理,固定延遲指令需要在發射後的固定週期數內完成,以保證程式碼的正確性。
(2)排程策略
為了探究指令發射排程器的策略,我們設計了許多涉及多個執行緒束的不同測試用例,並記錄每個週期中指令發射排程器選擇哪個執行緒束進行指令發射。這些資訊透過能夠儲存 GPU 當前時鐘週期的指令收集而來。然而,由於硬體不允許連續發射兩條這樣的指令,我們在它們之間使用了一定數量的其他指令(通常是 NOP 指令)。我們還改變了 Yield 和停頓計數器控制位的具體值。
實驗結果使我們得出結論,執行緒束排程器採用GTO策略,如果同一執行緒束中的指令滿足上述資格標準,就選擇該執行緒束的指令。當切換到不同執行緒束時,會選擇滿足資格標準的最年輕執行緒束。
圖 4 透過我們的一些實驗示例說明了這種指令發射排程器策略。該圖描繪了在同一子核心中執行四個執行緒束時,三種不同情況下的指令發射情況。每個執行緒束執行相同的程式碼,該程式碼由 32 條可在每個週期發射一條的獨立指令組成。
在第一種情況(圖 4a)中,所有停頓計數器、依賴掩碼和 Yield 位都設定為零。排程器從最年輕的執行緒束 W3 開始發射指令,直到它在指令快取(Icache)中發生缺失。由於快取缺失,W3 沒有有效指令,因此排程器切換到從 W2 發射指令。W2 在 Icache 中命中,因為它重用了 W3 帶來的指令,當 W2 到達 W3 發生缺失的位置時,缺失已經得到處理,並且所有剩餘指令都在 Icache 中找到,所以GTO排程器發射該執行緒束的指令直到結束。之後,排程器繼續從 W3(最年輕的執行緒束)發射指令直到結束,因為此時所有指令都已存在於 Icache 中。然後,排程器切換到從 W1 從頭到尾發射指令,最後對 W0(最老的執行緒束)執行相同操作。

圖 4b 展示了每個執行緒束的第二條指令將其停頓計數器設定為 4 時的指令發射時間線。可以觀察到,排程器在兩個週期後從 W3 切換到 W2,再過兩個週期後切換到 W1,然後又過兩個週期後回到 W3(因為 W3 的停頓計數器變為零)。一旦 W3、W2 和 W1 執行完畢,排程器開始從 W0 發射指令。在發射 W0 的第二條指令後,排程器產生四個空閒週期,因為沒有其他執行緒束可以掩蓋停頓計數器帶來的延遲。
圖 4c 展示了每個執行緒束的第二條指令設定了 Yield 位時排程器的行為。可以看到,在發射每個執行緒束的第二條指令後,排程器會切換到其餘執行緒束中最年輕的執行緒束。例如,W3 切換到 W2,W2 又切換回 W3。我們還測試了設定 Yield 位且沒有更多可用執行緒束的場景(圖中未顯示),觀察到排程器會產生一個週期的空閒。
我們將這種指令發射排程器策略稱為CGGTY,因為編譯器透過控制位(停頓計數器、Yield 位和依賴計數器)協助排程器工作。
不過,我們僅在同一執行緒塊(CTA)內的執行緒束中證實了這種行為,因為我們尚未設計出可靠的方法來分析不同 CTA 中執行緒束之間的互動。
2
前端
根據英偉達的多篇文件中的圖表,流多處理器(SM)有四個不同的子核心,執行緒束以迴圈方式均勻分佈在子核心之間(即 warp ID %4)。每個子核心都有一個私有的 L0 指令快取,它與一個為 SM 中所有四個子核心共享的 L1 指令快取相連。我們假設存在一個仲裁器來處理不同子核心的多個請求。
每個 L0 指令快取都有一個指令預取器。我們的實驗證實了 Cao 等人先前的研究,該研究表明指令預取在 GPU 中是有效的。雖然我們無法確定英偉達 GPU 中使用的具體設計,但我們懷疑它是一種簡單的方案,如流緩衝區,在發生快取缺失時預取連續的記憶體塊。根據我們的分析,我們假設流緩衝區的大小為 16,下文將對此進行詳細說明。
我們透過實驗無法確定確切的指令獲取策略,但它肯定與指令發射策略類似;否則,在指令緩衝區中找不到有效指令的情況會相對頻繁地發生,而我們在實驗中並未觀察到這種情況。基於此,我們假設每個子核心每個週期可以獲取並解碼一條指令。取指排程器會嘗試從先前週期(或最近發射指令的週期)發射指令的同一執行緒束中獲取指令,除非它檢測到指令緩衝區中已有的指令數量加上正在獲取的指令數量等於指令緩衝區的大小。
在這種情況下,它會切換到指令緩衝區中有空閒條目的最年輕執行緒束。我們假設每個執行緒束的指令緩衝區有三個條目,因為考慮到從取指到發射有兩個流水線階段,這樣足以支援貪心策略。如果指令緩衝區的大小為兩個條目,指令發射排程器的貪心策略將會失敗。例如,假設指令緩衝區大小為兩個,所有請求都在 Icache 中命中,所有執行緒束的指令緩衝區都已滿,在第 1 個週期,一個子核心從執行緒束 W1 發射指令並從 W0 取指。在第 2 個週期,W1 的第二條指令將被髮射,第三條指令將被獲取。在第 3 個週期,W1 的指令緩衝區中將沒有指令,因為指令 3 仍在解碼中。
因此,其貪心行為將失敗,它將不得不切換到從另一個執行緒束髮射指令。正如我們的實驗所證實的,當指令緩衝區有三個條目時,這種情況不會發生。值得注意的是,文獻中的大多數先前設計通常假設取指和解碼寬度為兩條指令,且每個執行緒束的指令緩衝區有兩個條目。此外,這些設計僅在指令緩衝區為空時才取指。因此,貪心選擇的執行緒束總是至少在連續兩條指令之後就會改變,這與我們的實驗觀察結果不符。
3
暫存器檔案
我們透過執行不同組合的 SASS 彙編指令進行了大量實驗,以揭示暫存器檔案的組織結構。例如,我們編寫了對暫存器檔案埠施加不同壓力的程式碼,包括使用和不使用暫存器檔案快取的情況。
現代英偉達 GPU 擁有多種暫存器檔案:
-
常規暫存器檔案:近期的英偉達架構每個 SM 有 65536 個 32 位暫存器,用於儲存執行緒操作的值。這些暫存器以 32 個為一組進行排列,每組對應一個執行緒束中 32 個執行緒的暫存器,因此共有 2048 個執行緒束暫存器。這些暫存器在子核心之間平均分配,每個子核心中的暫存器被組織成兩個儲存體。特定執行緒束使用的暫存器數量可以在 1 到 256 之間變化,這在編譯時確定。每個執行緒束使用的暫存器越多,SM 中能夠並行執行的執行緒束就越少。
-
統一暫存器檔案:每個執行緒束有 64 個專用的 32 位暫存器,用於儲存該執行緒束中所有執行緒共享的值。
-
謂詞暫存器檔案:每個執行緒束有八個 32 位暫存器,每個位由執行緒束中的不同執行緒使用。這些謂詞用於執行緒束指令,以指示哪些執行緒必須執行該指令,在分支情況下,還用於指示哪些執行緒必須執行分支,哪些不執行。
-
統一謂詞暫存器檔案:每個執行緒束有八個 1 位暫存器,用於儲存執行緒束中所有執行緒共享的謂詞。
-
SB 暫存器:如第 4 節所述,每個執行緒束有六個暫存器,稱為依賴計數器,用於跟蹤可變延遲依賴關係。
-
B 暫存器:每個執行緒束至少有 16 個 B 暫存器,用於管理控制流重新收斂。
-
特殊暫存器:還有各種其他暫存器,用於儲存特殊值,如執行緒 ID 或塊 ID。
與先前的工作不同,現代英偉達 GPU 並未使用運算元收集器來處理暫存器檔案埠的衝突。運算元收集單元會在指令發射和寫回之間的時間間隔引入可變性,這使得英偉達指令集架構(ISA)無法實現固定延遲指令,因為如第 4 節所述,為了正確處理依賴關係,固定延遲指令的延遲必須在編譯時確定。我們透過檢查特定的生產者 – 消費者指令序列在改變進入同一儲存體的運算元數量時的正確性,證實了運算元收集器的不存在。我們觀察到,無論暫存器檔案埠衝突的數量如何,指令中為避免資料風險所需的停頓計數字段的值以及執行指令所需的時間都保持不變。
我們的實驗表明,每個暫存器檔案儲存體都有一個 1024 位的專用寫埠。此外,當載入指令和固定延遲指令在同一週期完成時,延遲一個週期的是載入指令。另一方面,當兩個固定延遲指令之間存在衝突時,例如一條 IADD3 指令後面跟著一條使用相同目標儲存體的 IMAD 指令,它們都不會延遲。這意味著使用了類似於 Fermi 架構中引入的結果佇列來處理固定延遲指令。這些指令的消費者不會被延遲,這意味著在結果寫入暫存器檔案之前,使用了旁路技術將結果轉發給消費者。
關於讀取,我們觀察到每個儲存體的頻寬為 1024 位。這些測量結果是透過各種測試獲得的,這些測試記錄了連續的 FADD、FMUL 和 FFMA 指令的執行時間。例如,兩個源運算元都在同一儲存體中的 FMUL 指令會產生一個週期的空閒,而如果兩個運算元在不同儲存體中,則不會產生空閒。三個源運算元都在同一儲存體中的 FFMA 指令會產生兩個週期的空閒。
遺憾的是,我們未能找到一種適用於所有研究情況的讀取策略,因為我們觀察到空閒週期的產生取決於指令的型別以及指令中每個運算元的任務。我們發現,與幾乎所有測試實驗都最匹配的近似方案是,在固定延遲指令的指令發射和運算元讀取之間設定兩個中間階段,我們稱之為控制階段和分配階段。前者已在前文中解釋過。後者負責保留暫存器檔案讀埠。暫存器檔案的每個儲存體都有一個 1024 位的讀埠,透過使用暫存器檔案快取來緩解讀取衝突(稍後會詳細介紹)。
我們的實驗表明,所有固定延遲指令讀取源運算元都需要三個週期,即使在某些週期指令處於空閒狀態(例如當只有兩個源運算元時),因為 FADD 和 FMUL 指令與 FFMA 指令具有相同的延遲,儘管它們少一個運算元,而且 FFMA 指令無論其三個運算元是否在同一儲存體中,延遲始終相同。如果處於分配階段的指令意識到它無法在接下來的三個週期內讀取所有運算元,它將停留在這個階段(使流水線向上遊停頓)併產生空閒週期,直到它能夠在接下來的三個週期內保留讀取源運算元所需的所有埠。
(1)暫存器檔案快取
在 GPU 中使用暫存器檔案快取(RFC)是為了緩解暫存器檔案埠的競爭並節省能源。
透過實驗,我們觀察到英偉達的設計與 Gebhart 等人的工作類似。與該設計一致,RFC 由編譯器控制,並且僅用於在常規暫存器檔案中有運算元的指令。關於最後結果檔案結構,我們所說的結果佇列的行為類似。然而,與上述論文不同,這裡沒有使用兩級指令發射排程器,如前文所述。
關於 RFC 的組織,我們的實驗表明,它在每個子核心的兩個暫存器檔案儲存體中各有一個條目。每個條目儲存三個 1024 位的值,每個值對應指令可能擁有的三個常規暫存器源運算元之一。總體而言,RFC 的總容量為六個 1024 位運算元的值(子條目)。需要注意的是,有些指令的某些運算元需要兩個連續的暫存器(例如張量核心指令)。在這種情況下,這兩個暫存器分別來自不同的儲存體,並被快取在各自相應的條目中。
編譯器管理分配策略。當一條指令被髮射並讀取其運算元時,如果編譯器為某個運算元設定了重用位,該運算元就會被儲存在 RFC 中。如果後續指令來自同一執行緒束,其暫存器 ID 與 RFC 中儲存的 ID 一致,並且運算元在指令中的位置與觸發快取的指令中的位置相同,那麼這條後續指令將從 RFC 中獲取其暫存器源運算元。無論 RFC 中是否命中,當對同一儲存體和運算元位置的讀取請求到達時,快取的值將不可用。清單 2 中的示例 2 說明了這一點;為了讓第三條指令在快取中找到 R2,第二條指令必須設定 R2 的重用位,儘管 R2 已經在快取中為第二條指令所用。清單 2 還展示了另外三個示例來說明 RFC 的行為。

4
記憶體流水線
在現代NVIDIA GPU中,記憶體流水線的初始階段由各個子核心(sub-core)獨立處理,而執行實際記憶體訪問的最後階段則由四個子核心共享,這是因為資料快取(data cache)和共享記憶體(shared memory)是所有子核心共用的資源[20,28]。本節我們將揭示每個子核心中載入/儲存佇列(load/store queues)的大小、子核心向共享記憶體結構傳送請求的速率,以及不同型別記憶體指令的延遲特性。
需要說明的是,GPU記憶體訪問主要分為兩種型別:一種是訪問共享記憶體(即SM本地記憶體,由執行緒塊內所有執行緒共享),另一種是訪問全域性記憶體(即GPU主存)。
為探究佇列大小和記憶體頻寬,我們設計了一系列實驗:每個子核心要麼執行一個warp的指令,要麼處於空閒狀態。每個warp執行一系列獨立的載入或儲存指令,這些指令總能命中資料快取或共享記憶體,並使用常規暫存器。表1展示了這些實驗結果,其中第一列顯示程式碼中的指令序號,後續四列則分別展示四種不同啟用子核心數量場景下,各子核心發射對應指令的時鐘週期。
透過觀察Ampere架構的表現可以發現:每個子核心能夠連續五個週期每週期發射一條記憶體指令,但從第6條記憶體指令開始會出現延遲,延遲週期數取決於啟用的子核心數量。由此我們可以推斷:1) 每個子核心最多能緩衝5條連續指令而不產生停頓;2) 全域性共享結構每兩個週期可以接收來自任意子核心的一個記憶體請求。例如,在多個子核心同時啟用的場景下,每個子核心的第6條及後續指令會間隔兩個週期才被髮射。
我們還發現:每個子核心的地址計算吞吐量為每4個週期完成一條指令。這一結論源自單啟用子核心場景下的測試資料——當僅有一個子核心啟用時,第6條指令發射後會出現4個週期的間隔。當兩個子核心啟用時,由於共享結構每兩個週期能處理一條指令,因此每個子核心可以保持每4個週期發射一條記憶體指令的速率。當更多子核心啟用時,共享結構將成為瓶頸。例如四個子核心同時工作時,由於共享結構的最大吞吐量為每兩個週期處理一條指令,每個子核心只能每8個週期發射一條指令。

關於子核心記憶體佇列的大小,我們估算其容量為4條指令,儘管每個子核心能夠緩衝5條連續指令。指令在進入處理單元時佔用佇列槽位,離開時釋放該槽位。
在快取命中且單執行緒執行的場景下,我們測量了各類記憶體指令的兩種延遲指標:第一種是載入指令從發射到其消費者指令(或覆寫同一目標暫存器的指令)能夠發射的最短時間間隔,我們稱之為RAW/WAW延遲(需注意儲存指令不會產生暫存器RAW/WAW依賴)。第二種是載入/儲存指令從發射到能夠發射寫入其源暫存器的指令的最短時間間隔,稱為WAR延遲。具體測量結果如表2所示。

研究發現:使用統一暫存器(uniform registers)計算地址的全域性記憶體訪問速度優於常規暫存器。這種差異源於地址計算效率的提升——統一暫存器由warp內所有執行緒共享,因此只需計算單個記憶體地址;而常規暫存器要求每個執行緒可能計算不同的記憶體地址。
此外,共享記憶體載入的延遲普遍低於全域性記憶體,且其WAR延遲在常規與統一暫存器場景下保持一致,而RAW/WAW延遲在使用統一暫存器時會減少1個週期。WAR延遲的一致性表明共享記憶體的地址計算是在共享結構中完成的(而非子核心本地結構),因此一旦讀取完源暫存器即可解除WAR依賴。
延遲特性還與讀寫資料的尺寸相關:對於WAR依賴,載入指令的延遲不受資料尺寸影響,因為其源運算元僅用於地址計算;而儲存指令的WAR延遲會隨寫入記憶體資料尺寸的增加而上升,因為這些資料作為源運算元需要從暫存器檔案讀取。對於RAW/WAW依賴(僅適用於載入指令),延遲隨讀取資料尺寸增大而增加,因為需要從記憶體向暫存器檔案傳輸更多資料。實測資料顯示該傳輸頻寬為512位元/週期。
我們還觀察到,常量快取的WAR延遲顯著高於全域性記憶體載入操作,而其RAW/WAW延遲卻略低。目前尚未能確認這一現象的具體成因。但透過實驗發現:固定延遲指令對常量記憶體的訪問與LDC(載入常量)指令使用了不同層級的快取。我們透過LDC指令預載入特定地址到常量快取並等待其完成後,再使用相同地址發出固定延遲指令,實測出現了79個週期的延遲(對應快取未命中狀態),而非預期的零延遲(命中狀態)。這表明固定延遲指令訪問常量地址空間時使用L0 FL(固定延遲)常量快取,而LDC指令則使用L0 VL(可變延遲)常量快取。
最後分析LDGSTS指令,該指令專為降低暫存器檔案壓力並提升資料傳輸效率而設計[38],可直接將全域性記憶體資料存入共享記憶體而無需經過暫存器檔案,從而節省指令和暫存器資源。測試表明其延遲與資料粒度無關:WAR依賴延遲恆定,因為地址計算完成後即可解除依賴;而RAW/WAW依賴則在完成讀取階段後解除,同樣不受資料粒度影響。
建模實現
我們從零開始設計了 Accel – sim 框架模擬器的流多處理器(SM)/ 核心模型,透過修改流水線來實現前文所闡述以及圖 3 中所展示的所有細節。下面概述主要的新增元件。
首先,我們為每個子核心添加了一個帶有流緩衝區預取器的 L0 指令快取。L0 指令快取和常量快取透過引數化的延遲與 L1 指令 / 常量快取相連。
我們根據之前的測量結果或賈等人所描述的安培架構來選擇快取的大小、層次結構和延遲。我們修改了指令發射階段,以支援控制位、對新新增的固定延遲指令的 L0 常量快取進行標籤查詢,以及實現新的編譯器引導的貪心優先且最年輕優先(CGGTY)指令發射排程器。我們納入了控制階段(在該階段指令會增加依賴計數器)和分配階段(在該階段固定延遲指令會檢查訪問暫存器檔案和暫存器檔案快取時是否存在衝突)。
對於記憶體指令,我們為每個子核心建模了一個新單元,併為子核心之間建模了一個共享單元,其延遲如前一節所述。
此外,由於阿卜杜勒哈利克等人已經證明張量核心指令的延遲取決於其運算元的數值型別和大小,因此我們調整了模型,以便為每種運算元型別和大小使用正確的延遲。
我們建模的其他細節包括:在每個子核心中沒有專用雙精度執行單元的架構中,為所有子核心共享的雙精度指令執行流水線。此外,我們精確地對使用多個暫存器的運算元的讀寫時序進行建模,而之前只是為每個運算元使用一個暫存器來進行近似處理。此外,我們修正了之前一項工作中報告的指令地址的一些不準確之處。
除了在模擬器中實現新的 SM / 核心模型外,我們還擴充套件了跟蹤工具。該工具已擴充套件到可以轉儲所有型別運算元(常規暫存器、統一暫存器、謂詞暫存器、立即數等)的 ID。另一個重要的擴充套件是能夠獲取所有指令的控制位,因為 NVBit 無法提供對這些控制位的訪問。這是透過在編譯時使用 CUDA 二進位制實用工具獲取 SASS(英偉達組合語言)程式碼來實現的。這意味著要修改應用程式的編譯方式,以便在編譯時生成依賴於微架構的程式碼,而不是使用即時編譯方法。不幸的是,對於少數核心(它們都屬於 Deepbench),英偉達工具無法提供 SASS 程式碼,這就導致無法獲取這些指令的控制位。為了模擬這些應用程式,我們對依賴關係採用混合模式,即在沒有 SASS 程式碼的核心中採用傳統的計分板方法;否則,就使用控制位。

我們擴充套件了該工具,使其能夠透過描述符捕獲對常量快取或全域性記憶體的訪問。儘管有人聲稱後一種型別的記憶體訪問是在 Hopper 架構中引入的,但我們注意到 Ampere 架構已經在使用它們了。描述符是一種對記憶體引用進行編碼的新方式,它使用兩個運算元。第一個運算元是一個統一暫存器,用於對記憶體指令的語義進行編碼,而第二個運算元則對地址進行編碼。我們擴充套件了跟蹤器以捕獲地址。遺憾的是,統一暫存器中編碼的行為仍未被跟蹤到。
我們計劃公開對 Accel-sim 框架所做的所有模擬器和跟蹤器更改。
驗證
在本節中,我們評估所提出的 GPU 核心微架構的準確性。首先,在 7.1 小節中描述所採用的方法。然後,在 7.2 小節中對設計進行驗證。接著,在 7.4 小節中研究暫存器檔案快取和暫存器檔案讀埠數量對準確性和效能的影響。隨後,在 7.3 小節中探討設計中兩個不同元件(如指令預取器)的影響,並在 7.5 小節中分析依賴檢查機制。最後,在 7.6 小節中討論該模型如何無縫適配除安培架構之外的其他英偉達架構。
1
方法
我們透過將模擬器的結果與在真實 GPU 上獲得的硬體計數器指標進行比較,來驗證所提出的 GPU 核心的準確性。我們使用了四種不同的安培架構GPU,其規格如表 4 所示。所有 GPU 均使用 CUDA 11.4 和 NVBit 1.5.5。我們還將我們的模型 / 模擬器與原始的 Accel-sim 模擬器框架進行比較,因為我們的模型是基於它構建的。

我們使用了來自 12 個不同套件的多種基準測試。所用套件列表以及應用程式數量和不同輸入資料集的數量可在表 3 中找到。總體而言,我們使用了 143 個基準測試,其中 83 個是不同的應用程式,其餘的只是改變了輸入引數。
2
效能準確性
表 4 展示了兩種模型(我們的模型和 Accel-sim 模型)相對於每個 GPU 真實硬體的平均絕對百分比誤差(MAPE)。可以看出,在所有評估的 GPU 中,我們的模型比 Accel-sim 模型準確得多,對於最大的 GPU—— 英偉達 RTX A6000,我們模型的 MAPE 不到 Accel-sim 模型的一半。在相關性方面,兩種模型非常相似,但我們的模型略勝一籌。

圖 5 展示了英偉達 RTX A6000 以及 143 個基準測試在兩種模型下的絕對百分比誤差(APE),這些基準測試按照每個模型的誤差從小到大排序。可以看到,對於所有應用程式,我們的模型始終比 Accel-sim 模型具有更低的絕對百分比誤差,並且在一半的應用程式中,差異相當顯著。此外,可以觀察到 Accel-sim 模型在 10 個應用程式上的絕對百分比誤差大於或等於 100%,在最壞的情況下達到了 543%,而我們的模型絕對百分比誤差從未超過 62%。如果將第 90 個百分位數作為尾部準確性的指標,Accel-sim 模型的絕對百分比誤差為 82.64%,而我們的模型為 31.47%。這證明了我們的模型比 Accel-sim 模型更加準確和可靠。
3
指令預取的敏感性分析
流緩衝區指令預取器的特性對全域性模型的準確性有很大影響。在本節中,我們分析了不同配置下的誤差,包括停用預取器、使用完美指令快取,以及使用大小為 1、2、4、8、16 和 32 條目的流緩衝區預取器。所有配置均基於英偉達 RTX A6000。每個配置的 MAPE 如表 5 所示。可以看出,大小為 16 的流緩衝區能獲得最佳的準確性。
從表 5 中的加速比結果中,我們還可以得出另一個結論:在 GPU 中,像流緩衝區這樣簡單直接的預取器的效能與完美指令快取相近。這是因為每個子核心中的不同執行緒束通常執行相同的程式碼區域,並且典型的通用計算 GPU(GPGPU)應用程式的程式碼控制流並不複雜,所以預取接下來的 N 行程式碼通常效果良好。需要注意的是,由於 GPU 不進行分支預測,因此實施 Fetch Directed Instruction 預取器並不值得,因為這需要新增一個分支預測器。

關於模擬準確性,我們得出結論:在不研究指令快取增強的情況下,使用完美指令快取通常能在保證相當準確性的同時提高模擬速度。然而,對於控制流較為關鍵的基準測試,如 dwt2d、lud或nw,使用完美指令快取或不使用流緩衝區會導致顯著的不準確(與使用完美指令快取相比,差異超過 20%;與不使用預取的指令快取相比,差異超過 200%)。這種不準確是因為完美指令快取無法捕捉到頻繁在不同程式碼段之間跳轉所帶來的效能損失,而不使用預取則會過度懲罰程式其他部分的執行,這也表明這些基準測試仍有改進的空間。
4
暫存器檔案架構的敏感性分析
表 6 展示了暫存器檔案快取的存在以及每個儲存體增加暫存器檔案讀埠數量對模擬準確性和效能的影響。它還展示了在理想情況下(所有運算元都能在單個週期內獲取)的結果。所有配置在所有基準測試中的平均效能和準確性相似。然而,對特定基準測試(如計算密集型的 MaxFlops(Accel-sim GPU Microbenchmark)和配置為 sgemm 引數的 Cutlass)進行更深入的研究,會發現更細微的差異。這兩個基準測試都嚴重依賴固定延遲的算術指令,這些指令對暫存器檔案訪問限制導致的停頓特別敏感,因為它們通常每條指令使用三個運算元。

對於 MaxFlops,無論 RFC 是否存在,效能都是相同的,因為只有一條靜態指令使用它。值得注意的是,當每個暫存器檔案儲存體使用兩個讀埠時,效能顯著提高了約 44%。考慮到每條指令通常使用三個運算元,而四個讀埠(每個儲存體兩個)足以滿足需求,這種改進是合理的。相比之下,從模擬準確性的角度來看,兩個讀埠的配置存在顯著偏差。
在配置為 sgemm 的 Cutlass 中,沒有暫存器檔案快取的單埠配置導致效能大幅下降(0.78 倍)。這一效能下降與觀察到的程式中 35.9% 的靜態指令至少在一個運算元中使用暫存器檔案快取的情況一致。然而,引入每個儲存體有兩個讀埠的暫存器檔案後,效能提高了 12%,這表明暫存器檔案及其快取的組織仍有改進的空間。
總之,暫存器檔案架構(包括其快取)對單個基準測試有重要影響,因此對其進行準確建模非常重要。每個儲存體一個埠加上一個簡單的快取,平均效能接近具有無限制數量埠的暫存器檔案,但對於某些個別基準測試,差距仍然很大,這表明這可能是一個有趣的研究領域。
5
依賴管理機制分析
在本小節中,我們分析了本文所解釋的軟硬體依賴處理機制對效能和麵積的影響,並將其與前幾代 GPU 使用的傳統計分板方法進行比較。表 7 展示了這兩個指標的結果。面積開銷是相對於一個 SM 的常規暫存器檔案面積(256KB)報告的。
基於傳統計分板的機制需要與可寫入的暫存器數量相同的條目數,即每個執行緒束 332 個條目(255 個用於常規暫存器,63 個用於統一暫存器,7 個用於謂詞暫存器,7 個用於統一謂詞暫存器)。此外,需要兩個計分板:一個用於檢測寫後寫(WAW)/ 寫後讀(RAW)衝突,另一個用於檢測讀後寫(WAR)衝突。這是因為儘管指令按順序發出,但由於可變延遲指令的存在,運算元的讀寫可能會亂序進行。例如,像記憶體指令這樣的可變延遲指令在發出後會被排隊,並可能在較年輕的算術指令寫入結果後讀取其源運算元,如果前者的源運算元與後者的目的運算元相同,就會發生讀後寫衝突。雖然第一個計分板每個條目只需要一位,但隨著每個條目的消費者數量增加,第二個計分板需要更多的硬體資源。假設每個條目支援多達 63 個消費者,單個執行緒束將需要 2324 位(332 + 332×log2 (63 + 1))來處理依賴關係。對於整個 SM,這相當於 111,552 位,佔暫存器檔案大小的 5.32%。
相比之下,本文提出的軟硬體機制需要六個 6 位的依賴計數器、一個 4 位的停頓計數器和一個 yield 位。這相當於每個執行緒束僅 41 位,每個 SM 為 1968 位。在開銷方面,這僅佔暫存器檔案大小的 0.09%,遠低於計分板方法。
總之,基於控制位的軟硬體協同設計優於其他替代方案,並且其面積開銷可以忽略不計。在支援每個 SM 多達 64 個執行緒束的 GPU(如英偉達 Hopper)中,與計分板相比,這種開銷差異更加顯著。對於控制位方案,其開銷為 0.13%,而對於具有 63 個消費者的計分板機制,開銷為 7.09%。此外,我們發現使用由兩個計分板組成的計分板機制(一個用於 RAW/WAW 衝突,另一個用於最多支援 63 個消費者的 WAR 衝突)在模擬準確性上與使用控制位相當。因此,對於那些不公開控制位值的應用程式(如 Deepbench 基準測試套件中的某些核心),這是一個有效的替代方案。
6
對其他英偉達架構的適用性
在本文中,我們主要關注英偉達安培架構。然而,我們在文中揭示的研究結果也適用於其他架構,如圖靈架構。除了報告四個安培架構 GPU 的結果外,表 4 還展示了一個圖靈架構 GPU 的結果,對於英偉達 RTX 2080 Ti,我們的模型相對於 Accel-sim 的 MAPE 提高了 6.94%。
雖然我們已經在圖靈架構和安培架構上驗證了該模型,但我們認為我們的研究結果仍然適用於其他英偉達架構。英偉達的公開宣告和 SM 架構圖表明,重大的架構變化主要集中在張量核心、光線追蹤單元的增強,以及同一 TPC 中 SM 之間的分散式共享記憶體等小功能上。儘管如此,為了使模型適用於這些其他架構,仍需要估計一些指令(如記憶體指令)的延遲。
相關工作
在學術界和工業界,模擬器是評估計算機架構設計理念的主要工具,因為評估新設計的成本較低。此外,模擬器也是檢驗設計是否接近實際硬體的有效工具。通用計算 GPU 也不例外,像英偉達這樣的領先廠商已經公開了部分內部模擬器(英偉達架構模擬器,NVArchSim 或 NVAS)的建立過程。在學術領域,有兩個流行的開源模擬器。第一個是 MGPUSim,它模擬 AMD GCN 3 架構,並針對支援虛擬記憶體的多 GPU 系統。另一個替代模擬器是 Accel-Sim 框架,這是一個週期精確的、最先進的跟蹤驅動模擬器,支援 CUDA 應用程式,模擬類似英偉達的現代架構,它基於早期的 GPGPU-Sim 3 模擬器。
在文獻中,有許多研究致力於逆向工程 CPU 的架構元件,例如英特爾的分支預測器或英特爾的快取設計等。
關於英偉達 GPU,已經有多項研究致力於揭示其特定元件的資訊。Ahn 等人和 Jin 等人分別針對英偉達 Volta 和安培架構的片上網路進行逆向工程。Lashgar 等人研究了英偉達 Fermi 和 Kepler 架構處理記憶體請求的能力。Jia 等人介紹了 Volta 和 Turing 架構的一些快取特性,如快取行大小和關聯性、指令延遲以及暫存器檔案的一些細節。Khairy 等人探索了 Volta 架構的 L1 資料快取和 L2 快取設計。Abdelkhalik 等人建立了安培架構中 PTX 和 SASS 指令之間的關係及其執行延遲。關於張量核心,不同的研究 [31, 43, 44, 53, 54, 72, 82, 91] 對其可程式設計性和微架構進行了研究。Zhang 等人對 Turing 和 Ampere 架構的 TLB 進行了逆向工程,目的是對多例項 GPU 進行攻擊。關於現代英偉達 GPU 架構的控制流,Shoushtary 等人為 Turing 架構的控制流指令定義了一種合理的語義,與實際硬體跟蹤相比,誤差僅為 1.03%。Amert 等人研究了英偉達 Jetson TX2 中的 GPU 任務排程器以及它與 ARM CPU 的互動。最後,Wong 等人描述了早期 Tesla 架構的許多元件,如快取、TLB、SIMT 控制流行為和協作執行緒陣列(CTA)屏障。
在以往針對其他 GPU 廠商的研究中,Gutierrez等人指出,在模擬過程中,直接使用 AMD GPU 的機器指令集架構(ISA)而非中間語言,對於準確評估瓶頸和潛在解決方案至關重要。此外,GAP 工具能夠識別真實的 AMD GPU 與在 gem5中模擬的 GPU 之間的差異,這使得 gem5 中 AMD GPU 模擬的準確性得到了提升。最後,Gera等人引入了一種模擬框架,並對英特爾的整合 GPU 進行了特性描述。
編譯器提示(也稱為控制位)至少從英偉達開普勒(Kepler)架構起就已在 GPU 中使用。格雷(Gray)等人發表了對這些控制位的描述。在開普勒、麥克斯韋(Maxwell)和帕斯卡(Pascal)架構中,每 3 到 7 條指令中通常就有一條是編譯器插入的提示指令。賈(Jia)等人指出,諸如 Volta 或 Turing 等較新的架構已將指令位寬從 64 位增加到 128 位。因此,新架構不再透過特定指令來實現提示功能,而是在每條指令中都包含提示位。這些位不僅旨在提升硬體效能,還能透過防止資料衝突來確保程式的正確性。CPU 也會利用編譯器提示,幫助硬體更好地決定如何使用不同的資源。這些提示用於支援 CPU 的不同元件,如資料旁路、分支預測和快取等。
據我們所知,我們的工作首次揭示了現代英偉達 GPU 的核心微架構,並開發出了精確的微架構模擬模型。我們在研究中發現的一些新特性包括:對控制位語義的完整定義以及支援這些控制位的微架構變化、指令發射排程器的行為、暫存器檔案及其相關快取的微架構,以及記憶體流水線的多個方面。這些方面對於準確建模現代英偉達 GPU 至關重要。
結論
本文透過在真實硬體上進行逆向工程,揭示了行業內現代英偉達 GPU 的微架構。我們剖析了指令發射階段的邏輯,包括分析執行緒束的就緒條件,並發現執行緒束之間的指令發射排程器遵循編譯器引導的貪心優先且最年輕優先(CGGTY)策略。此外,我們揭示了暫存器檔案的不同細節,例如埠數量及其寬度。我們還闡釋了暫存器檔案快取的工作原理。此外,本文展示了記憶體流水線的一些重要特性,如載入 / 儲存佇列的大小、子核心之間的競爭,以及記憶體指令粒度訪問如何影響延遲。此外,我們分析了取指階段,並提出了一種符合現代英偉達 GPU 要求的取指方案。
此外,本文透過整理、詳細解釋和擴充套件之前關於控制位的公開資訊,對其進行了總結。
我們還在模擬器中對所有這些細節進行建模,並將這個新模型與真實硬體進行比較,結果表明,該模型在週期準確性方面比以前的模型提高了 18.24% 以上,更接近實際情況。
此外,我們證明了在 GPU 中使用基於簡單流緩衝區的指令預取在模擬準確性和效能方面表現良好,接近完美的指令快取。我們還展示了現代英偉達 GPU 中基於控制位的依賴管理機制如何優於其他方案,如傳統的計分板機制。
最後,我們研究了暫存器檔案快取和暫存器檔案讀埠數量對模擬準確性和效能的影響。
總體而言,我們可以得出結論,GPU 是硬體與編譯器的協同設計,其中編譯器指導硬體處理依賴關係,並引入可以提高效能和能效的提示資訊。
致謝本文作者:
Rodrigo Huerta、José-Lorenzo Cruz、Mojtaba Abaie Shoushtary和Antonio González
END
👇半導體精品公眾號推薦👇
▲點選上方名片即可關注
專注半導體領域更多原創內容
▲點選上方名片即可關注
關注全球半導體產業動向與趨勢
*免責宣告:本文由作者原創。文章內容系作者個人觀點,半導體行業觀察轉載僅為了傳達一種不同的觀點,不代表半導體行業觀察對該觀點贊同或支援,如果有任何異議,歡迎聯絡半導體行業觀察。

今天是《半導體行業觀察》為您分享的第4034期內容,歡迎關注。
推薦閱讀



『半導體第一垂直媒體』
即時 專業 原創 深度
公眾號ID:icbank
喜歡我們的內容就點“在看”分享給小夥伴哦

