逆向英偉達GPU,解碼芯片龍頭的成功奧祕
依據《伯爾尼公約 Berne Convention》、香港、中國內地的法律規定,本網站對相應內容享有對應的版權。

2025-Jun-07

以下為文章正文:

如果您希望可以時常見面,歡迎標星收藏哦~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半導體精品公衆號推薦專注半導體領域更多原創內容關注全球半導體產業動向與趨勢*免責聲明:本文由作者原創。文章內容系作者個人觀點,半導體行業觀察轉載僅爲了傳達一種不同的觀點,不代表半導體行業觀察對該觀點贊同或支持,如果有任何異議,歡迎聯繫半導體行業觀察。今天是《半導體行業觀察》爲您分享的第4034期內容,歡迎關注。『半導體第一垂直媒體』實時 專業 原創 深度公衆號ID:icbank喜歡我們的內容就點“在看”分享給小夥伴哦

(請各位謹慎甄別內容,自擔風險。)