NVIDIA Nsight 圖形 的一個不太出名但很酷的功能是著色器探查器。這使您能夠在著色器中找到熱點,幫助您指導優化工作。它可以讓你深入了解為什么有時候表現不是你喜歡的。
在本文中,我們使用 NVIDIA Nsight 圖形 跟蹤分析工具來識別潛在的限制器,然后使用著色器探查器進行更深入的挖掘,以發現并修復問題。
第一步:從 GPU 跟蹤分析工具開始
我們總是建議從 Nsight Graphics GPU 跟蹤工具開始,而不是直接進入著色器探查器。這樣,您就可以了解任何給定 DX12 或 VK 工作負載的性能限制是什么。例如,如果真正的問題是 GPU 利用率低,因為有很多微小的調度,它們之間都有屏障,那么嘗試微調著色器是沒有意義的。
首先,設置與要分析的應用程序的連接。選擇 Connect 并填寫啟動游戲所需的參數(圖 1 )。
選擇GPU Trace 作為活動,將 Metric Set 配置為 高級模式度量 。 使用 高級模式度量 需要一個穩定且一致的框架,因為分析會在多個框架上進行多次傳遞。如果應用程序不滿足這些要求,可以使用 Nsight Graphics 內置的 C ++捕獲工具捕獲應用程序的一個幀,并創建一個新的 EXE ,重復播放同一幀。
選擇啟動 GPU Trace 啟動應用程序。當你到達你想要捕捉的畫面時,選擇生成 GPU Trace 捕獲或者按 F11 。
捕獲完成后,停止應用程序并打開跟蹤。選擇 Trace Analysis 。在的 Analysis 面板中GPU Trace(圖 2 ),雙擊或將鼠標懸停在要分析的范圍的標記上,在本例中,DispatchRays[0]
:
工具提示顯示了該工具在此 GPU 工作負載中檢測到的所有性能增益機會的簡潔視圖,按其預計的 GPU 幀時間增益排序。工作負載有以下限制:
- L2 Limited : L2 受限可能表明存在問題。有了工作量方面的知識,這不一定是你所期望的。
- L1 長記分板暫停的翹曲: 這是翹曲停止的常見原因,通常是由于紋理提取。如果在啟動紋理查找和使用查找的結果之間沒有足夠的工作,則會暫停扭曲,直到滿足紋理查找。
- 扭曲被本地內存限制暫停 :本地內存是“線程本地”。它是每個線程的本地內存,而不是線程組中所有線程之間共享的組共享內存。著色器不需要任何本地內存,所以這很有趣。本地內存節流意味著什么?這里還有很多東西要學。
選擇 SM 翹曲延遲 和 扭曲被本地內存限制暫停 。
解釋窗口對問題進行了更有意義的描述,并提供了一些有用的建議。它建議啟動著色器探查器,以定位具有lg_throttle
暫停的特定 HLSL 指令。
第 2 步:切換到著色器探查器
在使用著色器探查器之前,務必確保 Nsight Graphics 可以訪問著色器的符號。實現這一點的最簡單方法是確保著色器為 使用/ Zi 選項編譯 ,并將符號嵌入著色器二進制文件中。
有時,最好配置編譯,使符號進入外部 PDB 文件。在這種情況下,請確保在 Tools 、 Options 下指定正確的路徑。
當 Nsight Graphics 可以看到著色器符號時,它可以將著色器中的位置映射回源代碼,這使您更容易判斷發生了什么。如果 Nsight Graphics 無法訪問符號,則只能看到著色器反匯編(例如, DXIL )。
著色器探查器是幀探查器的一部分。再次連接到應用程序,但這次選擇 Activity 下的 Frame Profiler 。當您選擇 發射架剖面儀 時,應用程序應該在這個 HUD (圖 4 )的頂部啟動。

導航至應用程序中要配置文件的部分,然后按 F11 鍵捕獲一幀進行分析。從這里,在 Nsight Graphics 中選擇 Profile Shaders 。這將運行一個簡短的采樣會話,然后向您展示一個摘要視圖(圖 5 )。

這是一個故障。
Function Summary 按在這些著色器中命中的采樣數的順序顯示頂級著色器的列表。這是一個很好的著色器延遲代理,可以讓您專注于可以從優化中獲得最大好處的著色器。
在 Correlation 列中,有多個綠色記號,它們總是好的。在本例中,這意味著 Nsight Graphics 能夠將樣本與源代碼關聯起來。
要打開著色器視圖,請選擇第一個文件名。左邊是源代碼,右邊是 DXIL 。在本文中,您不必關心 DXIL ,所以將視圖更改為僅使用 HLSL
這很微妙,但在最右邊的滾動條右邊有一個重要的指令樣本熱圖。回想起GPU Trace 分析建議你找lg_throttle
攤位。上面說:
LSU 是執行對本地和全局內存訪問的單元。
運行著色器探查器,找到哪個 HLSL 指令的 lg _ thottle 暫停最多。
是否在本地范圍內聲明動態索引數組?
著色器是否有導致溢出的注冊壓力?
如果一級和二級命中率很低,那么盡量減少未命中率。
在著色器探查器中,由于lg_throttle
原因,顯示為 LGTHR 的采樣被暫停。
“是否在本地范圍內聲明了動態索引數組?”
動態索引數組由一個變量索引,其中索引的值在編譯時是未知的。
當這種情況發生時,編譯器通常會將數組放入本地內存,而不是放在寄存器中。內存比寄存器慢。
下面的代碼示例顯示了一個動態索引數組。
vertUvs[vertexOrder[0]] = cornerUv + du; vertUvs[vertexOrder[1]] = cornerUv + dv; vertUvs[vertexOrder[2]] = cornerUv;
怎么回事?看起來代碼以不同的順序填充數組,這取決于三角形是否翻轉。
int3 vertexOrder = isFlipped ? int3(2, 1, 0) : int3(0, 1, 2);
動態索引該數組的行為會使編譯器將該數組移動到內存中。它會影響這個代碼位以及引用該數組的所有代碼位。這就是為什么convertTriangleBaryUvsToBaryVws
也很熱門。
你能在沒有動態索引的情況下做到這一點嗎?是的,你可以。更改翻轉方式的結果如圖 7 所示。
那些特定的攤位被取消了。它將此調度的時間從 8.67 毫秒減少到 7.1 毫秒。它不僅提高了著色器代碼的效率,而且由于內存流量減少,還大大減少了 L2 中的限制器。


總結
NVIDIA Nsight 圖形 是分析渲染工作負載的強大工具。這是一個快速的演練,只涉及一些功能。我們強烈建議使用它。
免責聲明
從驅動程序版本 467.07 開始,本文中的測試和結果都是正確的。驅動程序和編譯器開發一直在繼續。這意味著優化機會也會隨著時間的推移而改變。
?
?