如何通過 PCIe 總線優(yōu)化從 CPU 到 GPU 的 DX12 資源上傳是一個老問題,有許多可能的解決方案,每個解決方案都有其優(yōu)缺點(diǎn)。在這篇文章中,我將展示如何使用 NVAPI 將 DX12 上傳堆移動到 CPU-Visible VRAM ( CVV ),這是一個加速 PCIe 有限工作負(fù)載的簡單解決方案。
CPU-Visible VRAM :工具箱中的新工具
以頂點(diǎn)緩沖區(qū)( VB )上載為例,數(shù)據(jù)不能跨幀重用。將 VB 上載到 GPU 的最簡單方法是直接從 GPU 讀取 CPU 內(nèi)存:
首先,應(yīng)用程序創(chuàng)建 DX12 UPLOAD 堆或等效的 CUSTOM 堆。 DX12 上傳堆分配在系統(tǒng)內(nèi)存中,也稱為 CPU 內(nèi)存,其中 WRITE_COMBINE ( WC )頁面針對 CPU 寫入進(jìn)行了優(yōu)化。 CPU 首先將 VB 數(shù)據(jù)寫入此系統(tǒng)內(nèi)存堆。
其次,應(yīng)用程序使用 IASetVertexBuffers 命令將上載堆中的 VB 綁定到 GPU draw 命令。
在 GPU 中執(zhí)行繪制時,將啟動頂點(diǎn)著色器。接下來,頂點(diǎn)屬性提?。?VAF )單元通過 GPU 的二級緩存讀取 VB 數(shù)據(jù),二級緩存本身從存儲在系統(tǒng)內(nèi)存中的 DX12 上載堆加載 VB 數(shù)據(jù):
圖 1 直接從 DX12 上傳堆獲取 VB 。
來自系統(tǒng)內(nèi)存的 L2 訪問具有高延遲,因此最好在執(zhí)行 draw 命令之前通過將數(shù)據(jù)從系統(tǒng)內(nèi)存復(fù)制到 VRAM 來隱藏該延遲。
從 CPU 到 GPU 的預(yù)上載可以通過使用 copy 命令來完成,可以使用 COPY 隊(duì)列異步完成,也可以在主直接隊(duì)列上同步完成。
圖 2 使用 copy 命令將 VB 預(yù)加載到 VRAM
復(fù)制引擎可以在復(fù)制隊(duì)列中與其他 GPU 工作同時執(zhí)行復(fù)制命令,并且可以同時使用多個復(fù)制隊(duì)列。但是,使用異步復(fù)制隊(duì)列的一個問題是,您必須注意將隊(duì)列與 DX12 Fences 同步,這可能很難實(shí)現(xiàn),并且可能會有很大的開銷。
在 GTC 2021 的 Nsight Graphics : GPU Trace 的下一級優(yōu)化建議 會議上,我們宣布 NVIDIA GPU 上 DX12 應(yīng)用程序的替代解決方案是有效地使用 CPU 線程作為復(fù)制引擎。這可以通過使用 NVAPI 在 CVV 中創(chuàng)建 DX12 上載堆來實(shí)現(xiàn)。 CPU 然后通過 PCIe 總線將寫入此特殊上載堆的數(shù)據(jù)直接轉(zhuǎn)發(fā)到 VRAM (圖 3 )。
圖 3 在 CPU 線程中使用 CPU 寫操作將 VB 預(yù)加載到 VRAM
對于 DX12 ,以下 NVAPI 函數(shù)可用于查詢系統(tǒng)中可用的 CVV 量,并用于分配這種新風(fēng)格的堆( CPU – 可寫 VRAM ,具有快速 CPU 寫入和慢速 CPU 讀?。?/p>
NvAPI_D3D12_QueryCpuVisibleVidmem
NvAPI_D3D12_CreateCommittedResource
NvAPI_D3D12_CreateHeap2
這些新功能需要最新的驅(qū)動程序: 466 。 11 或更高版本。
NvAPI_D3D12_QueryCpuVisibleVidmem 應(yīng)報(bào)告以下 CVV 內(nèi)存量:
使用 Windows 11 (例如,使用 Windows11 內(nèi)幕預(yù)覽 )時 NVIDIA RTX 20xx 和 30xx GPU s 的容量為 200-256 MB 。
可調(diào)整大小的條_ RTX 30xx GPU s 在 Windows 10 或 Windows 11 中超過 256 MB ,且 NVIDIA 控制面板中的 可調(diào)整大小的條_ 報(bào)告為 NVIDIA 。有關(guān)如何啟用可調(diào)整大小欄的更多信息,請參閱 GeForce RTX 30 系列通過可調(diào)整大小的桿支撐加速性能 。
使用 Nsight Graphics 從 CPU-Visible VRAM 檢測并量化 GPU 性能增益機(jī)會
NVIDIA NSight 圖形 2021 。 3 中的 GPU 跟蹤工具可輕松檢測 GPU 性能提升機(jī)會。啟用 高級模式 時, GPU 內(nèi)的 Analysis 面板將根據(jù)預(yù)測的幀減少百分比,通過修復(fù)此 GPU 工作負(fù)載中的特定問題,跟蹤幀內(nèi)的顏色代碼 perf 標(biāo)記。
以下是在 RTX NVIDIA 3080 上,從 看門狗:軍團(tuán) ( DX12 )預(yù)發(fā)布版本中選擇 Analyze 后的幀的外觀:
圖 4 帶有顏色編碼 GPU 工作負(fù)載的 GPU 跟蹤分析工具
(越綠,幀上的預(yù)計(jì)增益越高)。
現(xiàn)在,選擇幀末尾的用戶界面繪制命令,分析工具顯示,修復(fù) 二級未命中到系統(tǒng)內(nèi)存 性能問題后 GPU 幀時間預(yù)計(jì)減少 0 。 9% 。該工具還顯示,通過二級緩存?zhèn)鬏數(shù)拇蠖鄶?shù)系統(tǒng)內(nèi)存流量是由基本引擎請求的,該引擎包括頂點(diǎn)屬性獲取單元:
圖 5 GPU 跟蹤分析工具,關(guān)注單個工作負(fù)載。
通過在 CVV 中分配此 draw 命令的 VB ,而不是使用常規(guī) DX12 上載堆分配系統(tǒng)內(nèi)存,此機(jī)制的 GPU 時間從 0.2 ms 減少到 0.01 ms 以下。 GPU 幀時間也減少了 0.9% 。在此工作負(fù)載中, VB 數(shù)據(jù)現(xiàn)在直接從 VRAM 獲取:
圖 6 GPU 跟蹤分析工具,在優(yōu)化了工作負(fù)載之后。
使用 Nsight 系統(tǒng)避免 CPU 讀取 CPU – 可見 VRAM
CPU 不應(yīng)讀取常規(guī) DX12 上載堆,而應(yīng)僅將其寫入。與常規(guī)堆一樣, CVV 堆的 CPU 內(nèi)存頁已啟用 寫合并 。這提供了快速的 CPU 寫入性能,但緩慢的非緩存 CPU 讀取性能。此外,由于從 CVV 讀取 CPU 會通過 PCIe 、 GPU L2 和 VRAM 進(jìn)行往返,因此從 CVV 讀取的延遲遠(yuǎn)大于從常規(guī) DX12 上載堆讀取的延遲。
要檢測應(yīng)用程序 CPU 的性能是否受到來自 CVV 的 CPU 讀取的負(fù)面影響,并獲取 CPU 調(diào)用導(dǎo)致這種情況的信息,我建議使用 Nsight 系統(tǒng) 2021.3 。
示例 1 : CVV CPU 讀取 ReadFromSubresource
下面是一個在 Nsight 系統(tǒng)跟蹤中從 DX12 ReadFromSubresource 讀取災(zāi)難性 CPU 的示例。為了捕獲此跟蹤,在獲取跟蹤時,我在 Nsight 系統(tǒng)項(xiàng)目配置中啟用了新的 收集 GPU 指標(biāo) 選項(xiàng),以及默認(rèn)設(shè)置,其中包括 樣本目標(biāo)過程 。
以下是 Nsight Systems 在放大一個代表性幀后顯示的內(nèi)容:
圖 7 Nsight 系統(tǒng)顯示 2 。 6 ms ReadFromSubresource 調(diào)用與來自 BAR1 的高 PCIe 讀取請求計(jì)數(shù)相關(guān)的 CPU 線程。
在這種情況下(單個 – GPU 機(jī)器), Nsight Systems 中的 對 BAR1 的 PCIe 讀取請求 GPU 指標(biāo)測量發(fā)送到 PCIe 的 CPU 讀取請求數(shù),以獲取 CVV ( BAR1 )中分配的資源。 Nsight Systems 顯示 CPU 線程上的長 DX12 ReadFromSubresource 調(diào)用與來自 CVV 的大量 PCIe 讀取請求之間存在明顯的相關(guān)性。因此,您可以得出結(jié)論,此調(diào)用很可能是從 CVV 執(zhí)行 CPU 回讀,并在應(yīng)用程序中修復(fù)此問題。
示例 2 : CVV CPU 從映射指針讀取
CPU 從 CVV 讀取的數(shù)據(jù)不限于 DX12 命令。當(dāng)使用 DX12 資源映射調(diào)用返回的任何 CPU 內(nèi)存指針時,它們可能發(fā)生在任何 CPU 線程中。這就是為什么建議使用 Nsight 系統(tǒng)對其進(jìn)行調(diào)試,因?yàn)槌诉x定的 GPU 硬件指標(biāo)外, Nsight 系統(tǒng)還可以定期對每個 CPU 線程的調(diào)用堆棧進(jìn)行采樣。
以下是 Nsight 系統(tǒng)的一個示例,其中顯示了從 CVV 進(jìn)行的 CPU 讀取與沒有 DX12 API 調(diào)用相關(guān),但與 CPU 線程活動開始相關(guān):
圖 8 Nsight Systems 顯示了執(zhí)行映射調(diào)用的 CPU 線程與對 BAR1 的 PCIe 讀取請求之間的相關(guān)性,之后該相關(guān)性立即增加。
通過懸停在 CPU 線程下面的橙色采樣點(diǎn),您可以看到該線程正在執(zhí)行一個名為 RenderCollectedTrees 的 C ++方法,這對查找正在進(jìn)行 CVV 堆讀/寫操作的代碼是有幫助的:
圖 9 Nsight Systems 顯示 CPU 線程的調(diào)用堆棧采樣點(diǎn),該線程與對 BAR1 的高 PCIe 讀取請求相關(guān)。
在這種情況下,提高性能的一種方法是對 CPU 內(nèi)存的單獨(dú)塊執(zhí)行讀/寫訪問,而不是在 DX12 上載堆中。完成所有讀/寫更新后,從 CPU 讀/寫內(nèi)存向上載堆執(zhí)行 memcpy 調(diào)用。
結(jié)論
在 Windows 11 PC 上運(yùn)行的所有 PC 游戲都可以在 NVIDIA RTX 20xx 和 30xx GPU s 上使用 256 MB 的 CVV 。 NVAPI 可用于查詢系統(tǒng)中可用 CVV 內(nèi)存的總量,并在此空間中分配 DX12 內(nèi)存。如果 CPU 從未從原始 DX12 上載堆讀取數(shù)據(jù),則只需更改分配堆的代碼即可將 DX12 上載堆替換為 CVV 堆。
要檢測將 DX12 上載堆移動到 CVV 時 Nsight 圖形 的性能提升機(jī)會,建議使用 GPU 中的 GPU 跟蹤分析工具。要檢測和調(diào)試從 CVV 讀取 CPU 時的性能損失,我建議在啟用 GPU 指標(biāo)的情況下使用 Nsight 系統(tǒng) 。
關(guān)于作者
Louis Bavoil 自 2007 年以來一直在 NVIDIA 的開發(fā)者技術(shù)小組工作,從事 GPU 性能優(yōu)化和 GameWorks 軟件開發(fā)的混合工作,目標(biāo)是幫助提高 PC 游戲的生產(chǎn)價值。
審核編輯:郭婷
-
NVIDIA
+關(guān)注
關(guān)注
14文章
5002瀏覽量
103233 -
gpu
+關(guān)注
關(guān)注
28文章
4749瀏覽量
129034 -
WINDOWS
+關(guān)注
關(guān)注
4文章
3551瀏覽量
88853
發(fā)布評論請先 登錄
相關(guān)推薦
評論