弄清楚如何在個人電腦上降低渲染應用程序的GPU幀時間可能是一項具有挑戰性的任務,即使是最有經驗的PC游戲開發人員也是如此。本博客文章描述了我們在NVIDIA內部使用的性能分類方法,使用NVIDIA特定的硬件度量標準來找出任何給定GPU工作負載(也稱為性能標記或調用范圍)的主要性能限制器。
我們的性能分類方法并非從假設或有關在GPU上呈現的內容的知識開始。相反,它僅從硬件指標開始,讓我們知道整個GPU的利用情況,哪些硬件單元和子單元限制了性能,以及它們運行到各自的峰值性能的接近程度(也稱為“速度光“或”SOL“)。如果應用程序不使用異步計算,則可以將此以硬件為中心的信息映射回圖形API和著色器正在執行的操作,從而為如何提高任何給定工作負載的GPU性能提供指導:
-
如果沒有GPU單元具有較高的吞吐量(與SOL相比),那么我們會努力提高至少一個單元的吞吐量。
-
如果一些GPU單元具有較高的吞吐量(與SOL相比),那么我們將弄清楚如何從該單元中刪除工作。
Nsight Range Profiler
從開普勒架構1(完全支持Maxwell,Pascal和VoltaGPU)開始,所有NVIDIA GPU上的DX11,DX12和OpenGL上的PerfWorks庫可以捕獲每個GPU工作負載的硬件指標。雖然PerfWorks頭文件尚未公開,但該庫現在可以通過公共工具使用:Nsight的Range Profiler:用于DX12,DX11和OpenGL 4.6(但不包括Vulkan)的Visual Studio Edition 5.5,以及Microsoft的“PIX在Windows上“用于DX12。
1從維基百科上可以看到,GeForce 600和700系列大多是開普勒,900系列是麥克斯韋,1000系列是帕斯卡,而TITAN V是沃爾塔。
第1步:鎖定GPU核心時鐘
首先,為了獲得最具確定性的測量結果,我們建議您在收集任何性能指標之前始終鎖定您的GPU核心時鐘頻率(并在解鎖之后進行解鎖,以獲得最佳性能,以及在GPU空閑或只是最小化功耗和噪聲時做桌面渲染)。在啟用了“開發者模式”的Windows 10上,可以通過運行一個簡單的DX12應用程序來完成此操作,該應用程序在虛擬DX12設備上調用SetStablePowerState(TRUE),然后在不釋放設備的情況下進入睡眠狀態,如本博文所述。
注意:從Nsight:Visual Studio版本5.5開始,Range Profiler現在可以在分析任何Range之前/之后有效地調用SetStablePowerState(),使用適用于所有Windows版本(不僅僅是Windows 10)的內部驅動程序API,也不需要操作系統將處于“開發者模式”。因此,在使用Nsight Range Profiler時,您不必擔心鎖定GPU Core時鐘。
第2步:用Nsight HUD捕捉畫面
對于非UWP(通用Windows平臺)應用程序,這可以通過將您的EXE(或批處理文件)拖放到Nsight安裝在桌面上的“NVIDIA Nsight HUD啟動器”快捷方式來完成,并達到您想要的游戲位置捕捉,然后:
-
按CTRL-Z在屏幕的右上部分顯示Nsight HUD,并
-
點擊Nsight HUD中的“暫停和捕捉幀”按鈕,或者按空格鍵開始捕捉。
您可以通過單擊“將捕獲保存到磁盤”按鈕將當前幀導出到Visual Studio C ++項目。(默認情況下,Nsight導出的幀被保存到C: Users ... Documents NVIDIA Nsight Captures ...)
你可以點擊“恢復”繼續玩你的游戲,以便找到你想要捕捉更多幀的其他位置。
注意:您可以跳過“將捕獲保存到磁盤”步驟并直接跳到下一步(Scrubber&Range Profiler分析),但我們建議始終將捕獲保存到磁盤,并將它們存檔,以便可以返回到它們你需要稍后。將導出的幀保存到磁盤可讓您稍后將數據附加到分析中,以便您或團隊中的其他人員可以嘗試重現您的結果。
在NVIDIA?(英偉達?)中,我們將性能分析視為一個科學流程,我們提供與分析相關的所有repro數據,并鼓勵同事重新繪制并審核我們的結果。根據我們的經驗,在進行性能優化嘗試(無論是否成功)之前和之后捕獲幀也是一種很好的做法,分析硬件度量標準如何變化并從結果中學習。
關于Nsight幀捕獲的補充說明:
-
對于Nsight框架,無論您的應用程序是以窗口模式,全屏模式還是全屏無邊界模式運行都無所謂,因為Nsight總是在隱藏窗口中運行框架。只要確保分辨率和圖形設置是你想要分析的。
-
對于DX12應用程序,我們假設沒有使用異步計算,否則某些硬件度量可能會受到GPU上多個同時執行的工作負載的影響。到目前為止,對于所有基于PerfWorks的分析,我們建議禁用在DX12應用程序中使用異步計算。
-
關于DX12異步復制調用(在COPY隊列中),可以在幀捕獲中使用這些調用,但是您應該知道,PerfWorks和Nsight目前不會單獨分析COPY隊列調用。因此,與其他DIRECT隊列調用并行執行的任何COPY隊列調用都可能會影響這些工作負載中的GPU DRAM流量。
-
將該exe文件拖放到“Nsight HUD啟動器”將不適用于UWP應用程序。在對UWP Nsight推出的做法,目前只能通過Visual Studio IDE中的支持。
第3步:分解GPU幀時間
GPU時間的自頂向下查看是找出哪些性能指標/工作負載在一個幀中最昂貴的好方法。對于HBAO +DX11測試應用程序,在GeForce GTX 1060 6GB上渲染SSAO為4K,在Nsight的Scrubber中,GPU幀時間分解如下所示:
圖1. Nsight中Scrubber的示例GPU幀時間細分:Visual Studio Edition 5.5。
在“Perf Markers”行中,Scrubber顯示通過D3D時間戳查詢測量的每個工作負載的GPU時間,以及每個工作負載正在使用的GPU幀時間百分比(排除當前調用)。在圖1的例子中,這一幀中哪個工作負載最為昂貴是顯而易見的:“DrawCoarseAOPS”,占GPU時間的49.1%。
注意:要重新顯示此結果,可以從GitHub下載HBAO +源代碼版本3.1,然后在Visual Studio中運行“SampleApp_D3D11”項目。要使RenderAO調用發出性能標記,可以在GFSDK_SSAO_D3D11 - >項目屬性 - > C / C + - >預處理器中定義ENABLE_PERF_MARKERS = 1。為了記錄,這里是框架的樣子:
步驟4:啟動Nsight Range Profiler
您可以打開您在步驟2中導出到磁盤的幀捕獲的Visual Studio解決方案文件,在Release x64中構建解決方案,然后轉到Visual Studio中的Nsight菜單,然后單擊“開始圖形調試”。
要到達Nsight Range Profiler,您可以啟動Nsight幀捕捉EXE,然后:
-
按CTRL-Z然后按空格鍵
-
ALT-Tab到您的Visual Studio窗口
-
找到Nsight在那里添加的Scrubber選項卡
-
右鍵單擊您想要分析的工作負載,然后單擊“Profile [Perf Markers] ...”
注意:如果由于某種原因,CTRL-Z + SPACE不適用于您的應用程序,您可以ALT-Tab到Visual Studio,然后單擊Visual Studio - > Nsight菜單 - >“暫停和捕獲幀”。
我們通過右鍵單擊洗滌器中的“DrawCoarseAOPS”框并執行“Profile [Perf Markers] DrawCoarseAOPS”,從步驟3的“DrawCoarseAOPS”工作負載調用Range Profiler(僅通過分析此調用范圍,除此之外別無其他)
圖2.從Scrubber窗口為給定的工作負載啟動Nsight Range Profiler。
Range Profiler在Nsight幀捕獲中注入PerfWorks調用,并為指定的工作負載收集一組PerfWorks度量。分析完成后,Nsight將在Scrubber下方的Range Profiler窗口的新部分中顯示收集的度量標準。
第5步:檢查頂級SOL和高速緩存命中率
我們首先檢查Range Profiler的“Pipeline Overview”Summary部分的指標。這只是PerfWorks衡量當前工作負載的一個視圖。通過將鼠標懸停在任何指標上,實際的Perfworks指標名稱將顯示在工具提示中:
圖3.顯示PerfWorks度量名稱和描述的Nsight Range Profiler工具提示。
5.1。每單位SOL%度量標準
要查看每個工作負載的首要頂級指標是GPU的每單元SOL%指標。這些傳達了每個單元與其最大理論吞吐量或光速(SOL)的接近程度。在高層次上,可以將每單元SOL%度量設想為實現的吞吐量與SOL吞吐量的比率。但是,對于具有多個子單元或并發數據路徑的單元,每單元SOL%是所有子單元和數據路徑的所有子SOL標準的最大值。
注:如果您不熟悉GPU中設備的名稱,請閱讀以下博客文章,其中提供了邏輯圖形管道如何映射到GPU架構中的GPU單元的高級概述:“三角形的壽命- NVIDIA的邏輯管道“,以及GTC 2016演示文稿中的第7至第25張幻燈片:”GPU驅動渲染“。在這種情況下:
-
“IA”(Input Assembler)加載索引和頂點(在頂點著色器被調用之前)。
-
SM(流式多處理器)運行著色器。
-
L2是連接到每個DRAM分區的二級緩存。
-
CROP的顏色寫入和混合渲染目標。
-
ZROP進行深度模板測試。
-
DRAM(范圍圖中的“內存”)是GPU視頻內存。
注意:在Nsight Range Profiler結果中,通過在管道概覽中選擇“Range Diagram”,可以找到圖形管道的簡化視圖及其與GPU單元的映射。在該圖中,每單位SOL%值顯示為綠色條形:
圖4. Nsight Range Profiler:流水線概覽 - >范圍圖。
如圖4所示,當今的GPU不是一個簡單的線性流水線(A→B→C→...),而是一個互連單元網絡(SM < - > TEX < - > L2,SM- > CROP < - > L2等)。簡單的“瓶頸”計算依賴于每個單元的固定上行和下行接口,但不足以推斷GPU的性能。因此,在進行我們的分析時,我們主要考察每個單位的SOL%度量,以確定單位和/或限制性能的問題。下一節將詳細討論這種方法。
5.2。“頂級SOL單位”
在我們的性能分類方法論中,我們始終始于查看前5個SOL單位及其相關的SOL%度量。這些是限制此工作負載的GPU性能的前5個硬件單元。Nsight Range Profiler在Pipeline Overview - Summary部分顯示前5個SOL%指標(又名“頂級SOL”),例如:
圖5. Range Profiler中的“Top SOLs”示例 - > Nsight中的Pipeline Overview:Visual Studio Edition 5.5。
情況1:SOL%> 80%
如果頂層SOL%值大于80%,那么我們知道GPU上的配置文件工作負載運行非常高效(接近最大吞吐量),為了加快速度,應該嘗試從頂層SOL單元中移除工作,它到另一個單位。例如,對于SM作為SOL%> 80%的頂級SOL單元的工作負載,可以嘗試機會性地跳過指令組,或考慮將某些計算移動到查找表。另一個例子是將結構化緩沖區加載移動到在統一訪問結構化緩沖區(所有線程加載來自相同地址的數據)中的著色器中的恒定緩沖區加載,以及受紋理吞吐量限制的工作負載(因為結構化緩沖區通過TEX單元加載)。
情況2:頂部SOL%<60%
如果最高SOL%值<60%,這意味著頂級SOL單元和所有其他具有較低SOL%的GPU單元未充分利用(空閑周期),運行效率低下(失速周期),或者未達到其快速路徑,原因是他們給出的工作量的細節。這些情況的例子包括:
-
該應用程序部分受CPU限制(參見第6.1.1節);
-
大量等待空閑命令或圖形< - >計算開關反復排空GPU管線(參見第6.1.2節);
-
TEX從具有格式,維度或過濾器模式的紋理對象中提取數據,使其在設計時以較低的吞吐量運行(請參閱這些用于GTX 1080的綜合基準測試)。例如,當采用三線性濾波對三維紋理進行采樣時,預計有50%的TEX SOL%;
-
內存子系統效率低下,例如TEX或L2單元中高速緩存命中率低,導致DRAM SOL%低的DRAM訪問稀疏,VB / IB / CB / TEX從系統內存取代GPU DRAM;
-
輸入組件獲取32位索引緩沖區(半速率與16位索引相比)。
注意:在這種情況下,我們可以使用最高SOL%值來導出可通過降低低效率在此工作負載上實現的最大增益的上限:如果給定的工作負載在其SOL的50%處運行,并且假設可以通過減少內部低效率將SOL%提高到90%,我們知道工作負載的最大預期收益為90/50 = 1.8x = 80%。
情況3:[60,80]中的最高SOL%
在這種情況下(灰色區域),我們遵循情況1(高位SOL%)和情況2(低位SOL%)的方法。
注:每單元SOL%度量標準都是相對于GPU周期(掛鐘)而定義的,這可能與活動周期(硬件單元不空閑的周期)不同。我們定義它們相對于經過周期而不是每單位有效周期的主要原因是通過給出它們所有的公分母來使SOL%指標具有可比性。定義它們相對于經過周期的另一個好處是任何限制整體GPU性能的GPU空閑周期都會被報告為該工作負載的最低SOL%值(我們的SOL引導分類中的頂級度量標準)。
5.3。次要SOL單位和TEX和L2命中率
Nsight Range Profiler報告前5個SOL單元的原因不僅僅是最大的一個,因為可能有多個硬件單元彼此交互,并且都在一定程度上限制了性能。所以我們建議根據SOL%值手動對SOL單元進行聚類。(實際上,10%的增量似乎可以很好地定義這些集群,但我們建議手動執行集群以避免遺漏任何內容。)
注意:我們還建議查看距離分析器“內存”部分中顯示的TEX(L1)和L2命中率。一般來說,大于90%的命中率很好,80%到90%之間好,80%以下(可能會顯著限制性能)。
全屏HBAO +模糊工作負載與前5個SOL:
SM:94.5%|TEX:94.5%|L2:37.3%|作物:35.9%|DRAM:27.7%
...既是SM又是TEX限制。由于SM和TEX SOL%值是相同的,我們可以推斷出SM性能很可能受SM和TEX單元之間接口吞吐量的限制:SM請求TEX或TEX將數據返回給SM 。
它具有TEX命中率88.9%和L2命中率87.3%。
在“TEX-Interface Limited Workload”附錄中查看此工作負載的研究。
從HBAO +例子中轉移出來,下面是我們最近分析的一些典型的游戲引擎工作負載。
具有頂級SOL的SSR工作負載:
SM:49.1%|L2:36.8%|TEX:35.8%|DRAM:33.5%|CROP:0.0%
...將SM作為主要限制器,將L2,TEX和DRAM作為次要限制器,TEX命中率為54.6%,L2命中率為76.4%。這種較差的TEX命中率可以解釋SM SOL%較低:由于TEX命中率較差(很可能是由于相鄰像素獲取了很遠的紋理元素),因此SM看到的平均TEX延遲比通常更高,更具挑戰性隱藏。
注意:這里的活動單元實際上是一個依賴鏈:SM - > TEX - > L2 - > DRAM。
此頂級SOL的GBuffer填充工作負載:
TEX:54.7%|SM:46.0%|DRAM:37.2%|L2:30.7%|CROP:22.0%
...將TEX和SM作為主要限制器,將DRAM和L2作為次要限制器,TEX命中率為92.5%,L2命中率為72.7%。
這款平鋪照明計算著色器具有頂級SOL:
SM:70.4%|L2:67.5%|TEX:49.3%|DRAM:42.6%|CROP:0.0%
...以SM&L2為主要限制器,TEX&DRAM為次要限制器,TEX命中率為64.3%,L2命中率為85.2%。
這個帶有頂級SOL的陰影貼圖生成工作負載:
IA:31.6%|DRAM:19.8%|L2:16.3%|VAF:12.4%|CROP:0.0%
...是IA限制的(輸入匯編器)并且具有較低的SOL%。在這種情況下,將索引緩沖區格式從32位更改為16位有幫助。TEX命中率無關緊要,因為TEX不在前5名SOL單位中。L2命中率為62.6%。
第6步:了解性能限制器
完成第5步后,我們知道每個感興趣工作負載的頂級SOL單元(GPU單元名稱和最大吞吐量的百分比),以及TEX和L2命中率。
我們知道,頂級的SOL GPU單元正在限制正在研究的工作負載的性能,因為這些單元正在運行最接近其最大吞吐量的單元。我們現在需要了解什么是限制這些top-SOL單元的性能。
6.1。如果頂部SOL%為低
如上面第5.2.2節所述,有多種可能的原因。我們經常將這些稱為病理 - 并且與現實生活中的患者一樣,工作負荷可能同時遭受多種病癥的影響。我們首先檢查以下指標的值:“GPU空閑%”和“SM單元活動百分比”。
6.1.1。“GPU空閑%”度量標準
Range Profiler的“GPU Idle%”度量標準映射到“gr__idle_pct”PerfWorks度量標準。它是當前工作負載下整個圖形和計算硬件管道閑置的GPU經過周期的百分比。這些“GPU空閑”周期是CPU無法為GPU提供足夠快的命令的周期,因此GPU管線完全是空的,無需處理任何工作。請注意,Wait For Idle命令導致的管道排空不計為“GPU空閑”。
如果針對任何給定的GPU工作負載看到此度量標準大于1%,那么您知道此工作負載由于某種原因受CPU限制,并且此CPU工作負載的性能影響至少為1%。在這種情況下,我們建議測量以下CPU調用花費的每個工作負載的總CPU時間,然后嘗試最小化最昂貴的CPU時間:
對于DX11:
-
沖洗{,1}
-
地圖
-
UpdateSubresource {,1}
對于DX12:
-
等待
-
ExecuteCommandLists
對于DX11和DX12:
-
任何創建或釋放呼叫
DX11說明:
-
ID3D11DeviceContext :: Flush強制執行命令緩沖區啟動,這可能需要Flush()調用在CPU上停止。
-
在連續幀中映射相同的分段資源時,在STAGING資源上調用ID3D11DeviceContext :: Map可能會導致CPU因資源爭用而停頓。在這種情況下,當前幀中的Map調用必須在內部等待,直到前一幀(使用相同的資源)在返回之前已經被處理。
-
使用DX11_MAP_WRITE_DISCARD調用ID3D11DeviceContext :: Map可能會導致CPU由于驅動程序用盡版本空間而停頓。這是因為每次執行Map(WRITE_DISCARD)調用時,驅動程序都會返回一個指向固定大小內存池的新指針。如果驅動程序用盡版本空間,Map調用將停止。
DX12注意事項:
-
每個ExecuteCommandLists(ECL)調用都有一些與之關聯的GPU空閑開銷,用于啟動新的命令緩沖區。因此,為了減少GPU空閑時間,我們建議將所有命令列表分配到盡可能少的ECL調用,除非您真的想要在幀中的某些點發生命令緩沖區啟動(例如,為了減少VR應用程序中的輸入延遲在飛行中有一個框架)。
-
當應用程序調用ID3D12CommandQueue :: Wait時,操作系統(Windows 10)將暫停向該命令隊列的GPU提交新的命令緩沖區,直到等待調用返回。
注意:每個API調用的CPU時間可以使用Nsight通過捕獲一個幀,然后進入Visual Studio - > Nsight - > Windows - > Events來測量:
6.1.2。“SM單元有效百分比”指標
“SM單元活躍%”度量標準報告每個SM實例至少有1個warp(32個線程)活動周期的百分比,在所有SM實例中平均。請注意,正在等待內存請求返回的變形會被記錄為“正在運行”/正在飛行中。
在Nsight:Visual Studio Edition 5.5中,此度量標準顯示在“管道總覽匯總”中的“范圍分析器結果”中。
對于全屏四元組或計算著色器工作負載,SM應該在超過95%的工作負載中處于活動狀態。如果不是,那么很可能SM之間存在不平衡,一些SM處于空閑狀態(沒有活動的翹曲),而其他SM處于活動狀態(至少有一個活動翹曲)。運行具有非均勻扭曲延遲的著色器時會發生這種情況。此外,具有少量小線程組的序列化調度調用不能足夠寬以填充GPU上的所有SM。
如果對于任何幾何渲染工作負載,SM活動百分比低于95%,您知道通過將異步計算工作與它重疊,可以在此工作負載上獲得性能提升。在DX12和Vulkan上,這可以通過使用Compute-only隊列來完成。請注意,即使SM活動百分比接近100%,也可以從異步計算獲得加速,因為SM可能被跟蹤為活動狀態,但可能能夠承受更多活動狀態。
對于任何工作負載而言,“SM單元活動百分比”可能低于95%的另一個原因是頻繁的GPU管線消耗(等待空閑命令,又名WFI),這可能是由以下原因造成的:
-
-
-
問題:出于著色器調度原因,HS和DS處于活動狀態時進行很多狀態更改會導致SM消失。
-
解決方案:盡量減少具有細化著色器的工作負載中的狀態更改(包括資源綁定)的數量。
-
-
問題:給定隊列上每批次的背靠背ResourceBarrier調用可能導致該隊列上的所有GPU工作都耗盡。
-
解決方案:為了最大限度地減少ResourceBarrier調用的性能影響,重要的是盡量減少執行ResourceBarrier調用的幀中的位置數量。
-
-
問題:默認情況下,具有綁定無人機的后續渲染調用通常由我們的驅動程序注入的GPU WFI命令進行保守分隔,以防止任何數據危害。
-
解決方案:可以使用以下調用來禁用無人機相關的等待空閑命令的插入:NvAPI_D3D11_ {Begin,End} UAVOverlap或NvAPI_D3D11_BeginUAVOverlapEx。
-
請注意,在DX12,OpenGL和Vulkan中,無人機相關的等待空閑命令由應用程序使用API調用(ResourceBarrier,glMemoryBarrier或vkCmdPipelineBarrier)顯式控制。
-
-
問題:在同一硬件隊列中的Draw和Dispatch調用之間切換會導致GPU WFI執行。此外,在僅計算工作負載中執行非CS狀態設置調用(例如,映射綁定到CS和圖形著色器階段的常量緩沖區)可能會導致WFI執行。
-
解決方案:批處理所有計算工作,并且不交叉圖形和計算API調用,包括Map(WRITE_DISCARD)調用在所有著色器階段綁定的“粘性”資源上。
-
頻繁計算< - >圖形開關在同一個DX11上下文中或在同一個DX12隊列中。
-
在DX11上,多個渲染調用具有相同的無人機界限,并且沒有提供給我們驅動程序的“無人機重疊”提示。
-
在DX12上,ResourceBarrier在障礙之間幾乎沒有任何工作。
-
數百在使用鑲嵌著色器/或幾何著色器的工作負載狀態的變化(除了硫苷被創建作為直通快速硫苷,使用NVAPI為DX11和DX12,或NV_geometry_shader_passthrough為GL)。
-
6.2。如果頂部SOL單位是SM
如果SM是最高SOL單位(或者以SOL%計),我們將分析Nsight Range Profiler中“SM問題利用率”指標的值。
SM單元是一個復雜單元,包含多個子單元,每個子單元具有相關的SOL%度量。PerfWorks庫允許查詢這些SM子SOL%指標之一:“sm__issue_active_per_elapsed_cycle_sol_pct”,該指標在范圍分析器中名為“SM IssueUtilizing Per Eilpsed Cycle”中公開。此度量是SM調度程序發出至少一條指令的已用周期的百分比。如果在給定的工作負載中,我們有“每個經過周期的SM問題利用率”==“SM SOL%”,那么我們知道最高SM子限制器是SM指令調度器,即工作負載是SM問題有限。
Range Profiler還在名稱“SM Issue Utilization Per Active Cycle”中公開“sm__issue_active_per_active_cycle_sol_pct”度量標準。與以前的度量唯一的區別在于,每個活動周期1通過SM活動周期數(具有至少一個活動激活的周期)而不是經過的周期(掛鐘)進行標準化。
“每個活動周期的SM問題利用率”度量標準對于確定給定的工作負載是否部分受“SM占用率”(“sm__active_warps_avg_per_active_cycle”PerfWorks度量標準)限制很有用。
案例1:“每個活動周期的SM問題利用率”> 80%
如果SM是最高的SOL單位,并且“每個活動周期的SM問題利用率”大于80%,那么當前工作負載主要受SM調度程序問題率的限制,因此增加SM占用率不會顯著提高性能(在工作量最少不超過5%)。
在這種情況下,性能分類過程的下一步是計算出哪些指令正在使SM調度器的帶寬飽和。通常,這是數學指令(FP32或整數操作數),但也可以是內存指令,如紋理提取或共享內存訪問。此外,TEX指令(SRV和UAV訪問)不太可能限制SM作為頂級SOL單元和SM問題利用率> 80%的工作負載的性能,除非TEX單元的SOL%值也接近于SM。
案例2:“每個活動周期的SM問題利用率”<60%
如本次GTC2013會議幻燈片15(t = 14分鐘)所述,當給定的warp指令不能發出時(因為它的操作數沒有準備好或者因為它需要執行的流水線子單元沒有準備好 - 我們呼叫這是一個扭曲失速),那么SM指令調度器會嘗試通過切換到不同的主動變形來隱藏延遲。因此,有兩種方法可以幫助SM調度程序為每個SM活動周期發出更多指令:
-
增加SM占用率(調度程序可以切換到的活動warp的數量)和
-
減少SM發布延遲時間(所以經線保持停滯狀態的周期更少)。
方法1:增加SM入住率
如果SM是最高SOL單位(或關閉),“SM SOL%”<80%,并且“?每次活動周期的SM問題利用率”<60%,則增加SM入住率應該可以提高性能。
為了增加SM占用率,首先必須弄清楚限制它的因素。
像素和計算著色器最常見的SM占用限制器是著色器使用的每個線程的硬件寄存器數量。
硬件寄存器計數對最大理論占用率(每個活動周期的活動變形數)的影響可在我們的CUDA占用率計算器中找到。以下是“計算能力”6.1的理論占有率圖,其中包括所有的GeForce GTX 10XX和Quadro Pxxxx GPU(GP10X):
圖6.“計算能力”的CUDA占用計算器圖表6.1。
除寄存器外,以下資源還可限制Maxwell,Pascal和Volta GPU上的SM占用率:
-
對于圖形著色器:
-
頂點著色器輸出屬性的總大小。
-
像素著色器輸入屬性的總大小。
-
HS,DS或GS的輸入和輸出屬性的總大小。
-
對于像素著色器,像素扭曲的亂序完成(通常由于諸如動態循環或早退出分支的動態控制流)。請注意CS沒有這個問題,因為CS線程組可以按任意順序完成。請參閱我們GDC 2016演講Gareth Thomas&Alex Dunn的“Practical DirectX 12”演講幻燈片。
-
-
對于計算著色器:
-
線程組大小可以直接影響SM占用率,因為線程組的線程組以全部或全部方式在SM上啟動(即,線程組的所有線程都具有必需的資源并將一起啟動,或者不會啟動將)。線程組大小越大,像共享內存和寄存器文件這樣的資源量化越粗糙。雖然有些算法可能真的需要大型線程組,但在所有其他情況下,開發人員應盡量將線程組大小限制為64或32個線程。這是因為64或32線程的線程組為我們的著色器編譯器提供了最大的靈活性,為著色器程序選擇最佳可能的寄存器目標。
-
此外,對于具有高寄存器使用率(> = 64)以及SM(Group H MemoryLarrierWithGroupSync()中的高線程組屏障停頓時間的著色器,將線程組大小降低為32可能會產生加速比,與64相比較。 > = 64寄存器指導可確保每個SM限制的32個最大線程組(CUDA占用率計算器中與架構相關的“線程塊/多處理器”限制)不會成為SM主要占用限制器。
-
每個線程組分配的共享內存字節總數也可以直接影響SM占用率,這可以通過將各種數字插入CUDA占用率計算器中看出。
-
我們關于實現占用率的CUDA Nsight文檔頁面包括計算著色器的一些額外可能的SM占用限制器:
-
線程組內的工作負載不平衡。
-
啟動的線程組太少。這對于圖形著色器來說也是一個問題,它沒有啟動足夠的warps來完全占用GPU Wait For Id之間的SM。
注意:實際上有兩種方法可以減少線程組大小:
-
方法1:將線程組大小降低N倍,同時將網格發射維度增加N.參見上文。
-
方法2:將N> = 2個線程的工作合并到一個線程中。這允許通過寄存器在N個合并線程之間共享公共數據,或者在寄存器中執行減少操作,而不是使用原子操作符(例如HLSL中的InterlockedMin)在共享內存中執行減少操作。此外,這種方法還具有在N個合并線程中自動分攤線程組統一操作的優點。但是,應該警惕這種方法可能導致登記數量膨脹。
注意:如果您想了解某個給定工作負載的SM占用量是否主要針對某個全屏Pixel Shader或某個計算著色器的寄存器數限制,則可以執行以下操作:
-
在Scrubber中添加...“程序范圍”,并找到您有興趣研究的著色器程序范圍。右鍵單擊您的程序范圍,啟動Range Profiler并檢查管道總覽摘要中的“SM占用率”值。
-
點擊Scrubber中的“Time(ms)”行,在Range中選擇一些渲染調用。將選項卡切換到API檢查器,選擇占用工作負載(PS或CS)中大部分周期的著色器階段,然后單擊著色器名稱旁邊的“統計”鏈接。
-
這會打開“Shaders”Nsight窗口(見下面的屏幕截圖),其中顯示了著色器的硬件寄存器數量,在“Regs”列中。請注意,您可能需要等待幾秒鐘才能填充著色器統計信息。
-
使用圖6中的CUDA占用率計算器圖查找與此寄存器計數相關的最大理論占用率,并將其與該范圍分析器為該著色器報告的實際“SM占用率”進行比較。
-
如果實現的占用率遠低于最大占用率,那么您知道SM占用率受限于每個線程的寄存器數量以外的其他因素。
圖7. Nsight的“Shaders View”,顯示“Regs”列中每個著色器的硬件寄存器數量。
為了減少為給定著色器分配的寄存器總數,可以查看DX著色器組件并研究著色器每個分支中使用的寄存器數量。硬件需要為最需要寄存器的分支分配寄存器,并且跳過該分支的經線以不理想的SM占用情況運行。
對于全屏通道(像素或計算著色器),解決此問題的典型方法是運行預處理,將像素分為不同的區域,并針對每個區域運行不同的著色器置換:
-
對于計算著色器,此SIGGRAPH 2016演示文稿介紹了一種使用DispatchIndirect調用將專用計算著色器應用于屏幕上不同圖塊的解決方案,每個著色器排列使用可變數量的線程塊:“Uncharted 4中的延遲照明” - Ramy El Garawany(淘氣狗)。
-
對于像素著色器,可以使用不同的專業化方法:全屏模板緩沖區可以在預處理中填充以對像素進行分類。然后,通過在像素著色器執行之前(這應該由我們的驅動程序自動完成)依靠模板測試來發生多個繪制調用,并且使用模板測試來丟棄當前著色器置換沒有的像素觸摸。此GDC 2013演示文稿使用此方法優化MSAA延遲渲染:“孤島危機3渲染技術” - Tiago Sousa,Carsten Wenzel,Chris Raine(Crytek)。
最后,為了更好地理解給定計算著色器的SM占用限制,您可以使用我們的CUDA占位計算器電子表格。要使用它,只需填寫GPU的CUDA計算能力以及著色器的資源使用情況(線程組大小,來自Shader視圖的寄存器計數以及共享內存大小(以字節為單位))。
方法2:減少SM失步延遲
除了增加SM占用率外,還有另一種方法可以增加SM問題利用率:通過減少SM發布 - 停止周期的數量。這些是指令執行周期之間的SM活動周期,在此期間,由于其操作數未準備就緒或由于數據路徑上的資源爭用而導致該指令需要在其上執行,因此warp指令被暫停。
如果所有著色器都在做數學運算和紋理提取,并且每個活動周期的SM問題利用率很低,那么可以合理地假設大多數停頓周期都來自于紋理提取結果的依賴關系,我們經常稱為“紋理延遲”。在這種情況下:
-
如果著色器包含一個可以在著色器編譯時可以知道迭代次數的循環(可能通過每個循環次數使用不同的著色器置換),那么嘗試強制FXC通過使用循環中的[unroll]循環屬性來完全展開循環HLSL。
-
如果著色器正在執行無法完全展開的動態循環(例如光線循環循環),請嘗試對紋理獲取指令進行批處理,以減少TEX依賴性延遲的數量(通過將獨立紋理拾取分批次編組為2到4在HLSL層面的背靠背說明)。
請參閱“優化光線行進循環”附錄。 -
如果著色器對給定紋理的每個像素的所有MSAA子采樣進行迭代,則可以在該紋理的單個TEX批處理指令中一起提取所有子采樣。由于MSAA子采樣在DRAM中彼此相鄰存儲,因此將它們一起提取可以最大化TEX命中率。
-
如果紋理加載是基于條件的,那么大多數時間都是真實的(例如,如果(idx
-
嘗試通過改進TEX和L2緩存命中率來減少TEX延遲。通過調整采樣模式以使相鄰像素/線程獲取更多相鄰紋理像素,通過使用mipmap(如果適用)以及通過減小紋理尺寸和使用更緊湊的紋理格式,可以提高TEX&L2命中率。
-
嘗試減少執行的TEX指令的數量(可能使用每個紋理指令使用分支,將其編譯為TEX指令謂詞,請參閱FXAA 3.11 HLSL的示例,例如:“if(!doneN)lumaEndN = FxaaLuma(...);”) 。
案例3:[60,80]中的問題利用率%
在這種情況下,我們遵循案例1(高問題利用率)和案例2(低問題利用率)的方法。
6.3。如果頂部SOL單元不是SM
6.3.1。如果頂層SOL單元是TEX,L2或DRAM
如果頂層SOL單元不是SM,而是其中一個內存子系統單元(TEX-L1,L2和DRAM),則可能導致性能較差的根本原因是TEX或L2緩存抖動-GPU友好的訪問模式(通常,在一個warp中相鄰的線程訪問相距甚遠的內存)。在這種情況下,頂部限制單元可能是TEX或L2,但根本原因可能在SM執行的著色器中,所以使用第6.2節中的方法(如果頂部SOL單元是SM )。
如果頂級SOL單元是DRAM,并且其SOL%值不差(> 60%),那么這個工作負載是DRAM吞吐量受限的,并且將其與另一個通道合并應該加速該幀。一個典型的例子是將伽馬校正通道與另一個后處理通道合并。
6.3.2。如果頂部SOL單位是CROP或ZROP
如果CROP是頂級SOL單元,則可以嘗試使用較小的渲染目標格式(例如R11G11B10F而不是RGBA16F),并且如果使用多個渲染目標,則可以嘗試減少渲染目標的數量。此外,更積極地殺死像素著色器中的像素可能是值得的(例如,對于某些透明效果,丟棄具有小于1%不透明度的像素)。查看此博客文章,獲取優化透明度渲染的更多可能策略:“透明度(或半透明度)渲染”。
如果ZROP是頂層SOL單元,則可以嘗試使用較小的深度格式(例如D16代替D24X8用于陰影貼圖,或用D24S8代替D32S8),以及以前后順序繪制不透明物體,以便ZCULL (粗粒度深度測試)有機會在調用ZROP和像素著色器之前丟棄更多的像素。
6.3.3。如果頂部SOL單位是IA
如前所述,IA會執行索引緩沖區和頂點緩沖區加載,以收集頂點著色器的輸入頂點。如果IA是頂級SOL單元,則可以嘗試使用16位索引緩沖區而不是32位索引緩沖區。如果這不會增加IA SOL%,則可以嘗試優化頂點重用和局部性的幾何圖形。此外,從其余屬性中分離出位置流對于z-only或陰影貼圖渲染可能是有益的。
概要
為了結束,我們的SOL引導式性能分類方法針對任何給定的GPU工作負載執行以下操作:
-
檢查“SOL SOL%”值(5.2節和5.3節)。
-
如果> 80%=>(A)嘗試從頂層SOL單元中取出工件(見第5.2.1節)。
-
如果<60%=>(B)嘗試增加SOL%(5.2.2和6.1節)。
-
(A)和(B)都可以。
-
-
如果SM是最高SOL單位(或以SOL%計)或“SM SOL%”低于80%:
-
如果> 80%=>(C)嘗試機會性地跳過指令組或考慮將某些計算移動到查找表(見第6.2.1節)。
-
如果<60%=>(D)嘗試增加SM占有率(飛行中活動的經紗數量)并減少SM發貨 - 停止周期的數量(見第6.2.2節)。
-
其他人同時做(C)和(D)。
-
檢查“每個活動周期的SM問題利用率”值。
-
-
如果其他單位是頂級SOL單位,請嘗試減少發送到該單位的工作量。(見第6.3節)。
要使用此方法,您只需要安裝Nsight:在PC上安裝Visual Studio Edition 5.5以及安裝最新的可用圖形驅動程序。
附錄:性能分類示例
示例1:TEX-Interface有限的工作負載
在GTX 1060 6GB @ 1506 Mhz上運行的HBAO +“DrawBlurXPS”全屏像素著色器工作負載在Nsight Range Profiler中具有以下指標:
-
頂部SOLs:SM:94.5%|TEX:94.5%|L2:37.2%|DRAM:27.6%
-
GPU空閑:0.0%=>不受CPU限制(參見第6.1.1節)
-
SM單元有效:99.5%=>無SM閑置問題(參見第6.1.2節)
-
SM問題使用率每循環周期:47.2%
-
每個活動周期的SM問題利用率:47.5%
-
SM占用:每個活動周期62.2個活動的經紗
-
TEX命中率:88.9%
-
二級命中率:87.3%
分析:
-
由于SM SOL%和TEX SOL%都非常接近(實際上相等),所以我們知道工作負載受到SM和TEX單元之間接口吞吐量的限制。
-
由于SM和TEX SOL%很高(94.5%),我們知道工作負載完全受SM和TEX單位的吞吐量的限制(95%與SOL%值一樣高)。
-
由于每個活動周期的SM問題利用率遠低于80%,我們知道指令調度器的帶寬遠未達到飽和。因此,增加SM占用率(每個活動周期的活動經紗數量)可能有助于理論上的幫助。但是由于SM SOL%(94.5%)太高,我們知道增加入住率并不會顯著提高績效。
-
TEX和L2的命中率很好(接近90%)。
結論:這個工作負載主要受SM-TEX接口帶寬的限制,唯一可以顯著加快執行速度的方法是減少執行的TEX指令的數量(例如,通過使用收集指令在一個TEX中執行4個單通道負載指令,或通過計算每個線程的多個輸出值并通過寄存器共享紋理采樣)。
示例2:數學有限的工作負載
HBAO +“DrawCoarseAOPS”工作負載在GTX 1060 @ 1506 Mhz上的Range Profiler中具有以下指標:
-
頂部SOLs:SM:93.4%|TEX:71.9%|L2:50.1%|DRAM:27.3%|CROP:3.6%
-
GPU空閑:0.0%=>不受CPU限制(請參閱第6.1.1節)
-
SM單元激活:99.5%=>沒有SM空閑問題(參見章節6.1.2)
-
每個周期的SM問題利用率:93.4%
-
每個活動周期的SM問題利用率:95.9%
頂部SOL分析:
-
最上面的SOL單元是SM,它的最大吞吐量為93.4%,輔助SOL單元(TEX,L2和DRAM)比SM SOL多20%,所以我們知道工作負載主要是SM通過限制。
-
第二個上限是TEX單位,以最大吞吐量的71.9%運行。
現在,讓我們進行以下思考實驗:如果此GPU中的TEX單元以某種方式無限快速完成,則工作負載仍將受到SM SM內93%SM內發生的工作的限制。這些工作中的一部分通常是來自著色器的紋理提取,因此如果TEX單元無限快地完成并且SM最初受TEX延遲限制,SM SOL可能會增加。但是,由于95%的價值與實踐中的SOL%值一樣高,我們知道SM SOL%無法通過使其他單位更快(或處理更少的工作)而顯著增加,因此我們知道唯一的顯著加速這一工作量的方法是找出SM內部的性能限制器。
附加分析:
-
由于SM是最大限制因素,并且“每次經過周期的SM問題利用率”==“SM SOL%”,因此我們知道此工作負載的最大SM子SOL度量標準為SM問題利用率%,即工作負載為主要受指令發行率的限制。
-
由于“每次活動周期的SM問題利用率”> 80%,我們知道工作負載不受SM占用率的明顯限制,也就是說,增加每個活動周期的活動warps數量并不會顯著提高性能。
-
我們可以推斷,性能不受紋理獲取指令的延遲的限制,否則我們將“SM活動周期的利用率”遠低于80%。
-
我們可以推斷性能不受TEX單元的限制,否則我們會讓TEX SOL%值更接近SM SOL%值。
結論:這個工作負載主要受著色器中數學指令的數量(FP32操作數和/或整數操作數和/或其他數學操作如rsqrt,pow,cos / sin等)的限制。為了加快速度,人們需要找到一種方法來以某種方式遮蔽較少的像素,或者每像素執行較少的數學指令。
示例3:TEX-Latency有限的工作負載
現在,我們來看看https://github.com/NVIDIAGameWorks/D3DSamples中的“Advanced Motion Blur”DX11 SDK示例
默認情況下,應用程序以720p窗口模式運行。為了使它以4K全屏模式啟動,我在main.cpp中進行了以下編輯:
#if0deviceParams.startfull-screen=false;deviceParams.backBufferWidth=1280;deviceParams.backBufferHeight=720;#其他deviceParams.startfull-screen=true;deviceParams.backBufferWidth=3840;deviceParams.backBufferHeight=2160;#萬一
接下來,我們可以在main.cpp中手動插入一個工作負載標記,它將被NSight攔截并在Range Profiler中成為“Perf Marker”范圍:
如果(g_view_mode==VIEW_MODE_FINAL){D3DPERF_BeginEvent(0x0,L“FinalPass”);//...ctx->Draw(6,0);D3DPERF_EndEvent();}
最后,我們可以按照第4節中的步驟使用Nsight Range Profiler來分析此工作負載。在GTX 1060 @ 1506 Mhz上,Range Profiler提供以下指標:
-
頂部SOLs:SM:40.7%|TEX:39.8%|L2:36.3%|作物:26.4%|DRAM:25.7%
-
GPU已用時間:0.70毫秒
-
GPU空閑:0.2%=>不受CPU限制(請參閱第6.1.1節)
-
SM單元有效:97.4%=>無SM閑置問題(請參閱第6.1.2節)
-
SM問題利用率每循環周期:40.7%
-
每個活動周期的SM問題利用率:41.8%
-
SM占用:每個活動周期37.0個活動經紗
-
TEX命中率:80.1%
-
二級命中率:83.0%
分析:
-
頂級SOL%單位是SM和TEX。
-
最高的SOL%值低于60%,所以此工作負載在GPU上運行效率低下。
-
由于“每個活動周期的SM問題利用率”遠低于80%,并且TEX SOL%非常接近SM SOL%,所以工作負載受TEX延遲限制。
-
由于頂級SOL單位是SM,“SM SOL%”<80%和“每個活動周期的SM問題利用率”<60%(請參見第6.2.2節),因此工作負載也受SM占用限制。
-
TEX和L2命中率很好。
實驗:刪除提前退出
根據第6.2.2節,我們知道,對于SM作為頂級SOL單元的工作負載,“SM SOL%”<80%和“每次活動周期的SM問題利用率”<60%,性能可能受到以下限制:
-
由于沒有足夠的指令級并行性來隱藏指令等待時間,所以出現高的問題延遲時間和/或
-
SM入住率低(由于沒有足夠的活躍經線來隱藏問題攤位)。
讓我們首先找出低SM占用率的主要原因。我們知道這個像素著色器有一個提前退出分支,如果分支被采用,通過輸出調試顏色,我們可以看到大多數像素正在提前退出。我們也從第6.2.2節知道,亂序像素著色器翹曲完成(與其啟動順序相比)可以限制SM占用。
為了驗證早退出分支實際上限制了占用率,讓我們做一下簡單地將它從像素著色器(ps_gather.hlsl)中移除的實驗:
#if0//如果速度太短,我們只顯示顏色紋理并退出如果(TempNX度量新的價值舊價值新舊GPU已用時間5.05毫秒0.70毫秒7.21x頂部SOL [0]SM:47.2%SM:40.7%1.16x頂部SOL [1]TEX:39.2%TEX:39.8%0.01XSM單元激活99.9%97.4%1.03X每個經過周期的SM問題利用率47.2%40.7%1.16x每個活動周期的SM問題利用率47.2%41.8%1.13xSM入住率62.037.01.68xTEX命中率85.8%80.1%1.07倍L2命中率95.2%83.0%1.15倍 表1.刪除了早期退出分支的新度量標準。
我們發現新的工作負載仍然受到SM占用的限制,但占用率(62.0)達到了硬件限制(64.0) - 即使在這種最大占用率的情況下,我們也看到工作負載仍然受TEX頂級SOL單元的TEX延遲限制SM和TEX。
顯然,由于取消了提前退出,工作量減慢了7倍,但這是可以的,因為我們希望以這種方式研究其性能限制器。這實際上是我們經常用來分析工作負載的一種方法,我們預計會出現多個性能問題:如果最初的問題太復雜,且SOL%s較低的根本原因不明確,則我們簡化問題(在此情況下,消除低占用率的預期根本原因),并對簡單問題重新進行分析,直到頂層SOL%s變好。這實際上是一個分而治之的性能調試方法。通過采取醫學比喻,我們正在消除一種病理學,以便對其他病理學的分析更清楚并且沒有“相聲”。
注意:對于簡化的問題,性能優化可能無法加速原始問題。但我們認為,即使發生這種情況,對大多數情況下簡單問題的分析仍然非常值得,因為這不僅有助于我們驗證我們對性能問題的理解是否正確,而且還有助于重新設計用于避免GPU性能低效的渲染算法。
結論:
此工作負載中SM占用率較差的主要原因是像素著色器提前退出。將這個像素著色器移動到計算著色器可以緩解這個問題(扭曲完成比給定線程組中的其他處理器更早完成將仍然限制SM占用),但是也會增加一些開銷,用于通過無人機寫入指令寫出結果。
或者,使用第6.2.2節中描述的模板掩模方法在這種情況下也應該有所幫助,因為它將使全屏像素著色器僅處理復雜像素,并且所有這些像素將按照啟動順序完成。
優化1:使用R11G11B10F而不是RGBA16F
原始SDK示例應用程序使用RGBA16F紋理格式存儲HDR顏色,這些顏色是由Motion Blur“Final Pass”過濾的顏色。
因為這個RGBA16F紋理的alpha通道從來沒有被這個應用程序實際使用過,所以我們可以將其更改為更緊湊的R11G11B10F格式,從而生成在這種情況下看起來相同的輸出圖像。實現這種優化只是main.cpp中的格式更改:
CreateTextureWithViews(設備,surface_desc->寬度,surface_desc->高度,#if0DXGI_FORMAT_R16G16B16A16_FLOAT,DXGI_FORMAT_R16G16B16A16_FLOAT,DXGI_FORMAT_R16G16B16A16_FLOAT,#其他DXGI_FORMAT_R11G11B10_FLOAT,DXGI_FORMAT_R11G11B10_FLOAT,DXGI_FORMAT_R11G11B10_FLOAT,#萬一這樣做可以通過提高TEX命中率來幫助減少顏色提取的TEX延遲:
度量新的價值舊值新舊GPU已用時間4.25毫秒5.05毫秒增加19%頂部SOL [0]SM:63.7%SM:47.2%1.35x頂部SOL [1]TEX:52.9%TEX:39.2%1.35xSM單元激活99.9%99.9%1.00倍每個經過周期的SM問題利用率63.7%47.2%1.35x每個活動周期的SM問題利用率63.8%47.2%1.35xSM入住率62.862.01.01xTEX命中率94.2%85.8%1.10xL2命中率91.5%95.2%0.96x表2.顏色格式從RGBA16F降至R11G11B10F的新指標。
優化2:循環展開
現在,讓我們來看看這個全屏像素著色器的HLSL。它包含以下循環,每個循環迭代有3個紋理提取,以及一個跳過循環體的動態分支,用于某個循環迭代索引:
for(inti=0;i使用以下命令行通過FXC運行此HLSL:
fxc/Tps_5_0/Ges/O3ps_gather.hlsl...在DXASM中產生以下控制流和紋理提取:
循環itofr5.w,r4.wger6.x,r5.w,cb0[21].zbreakc_nzr6.xieqr6.x,r3.x,r4.wif_nzr6.xmovr4.w,r3.w繼續endif...sample_l_indexable(texture2d)(float,float,float,float)r6.zw,r6.xyxx,t2.zwxy,s1,l(0.000000)... sample_l_indexable(texture2d)(float,float,float,float)r6.w,r6.xyxx,t1.yzwx,s1,l(0.000000)... sample_l_indexable(texture2d)(float,float,float,float)r6.xyz,r6.xyxx,t0.xyzw,s2,l(0.000000)madr5.xyz,r5.wwww,r6.xyzx,r5.xyzxiaddr4.w,r4.w,l(1)ENDLOOP我們知道這個工作量部分是TEX延遲有限。發生這種情況的原因是紋理提取和從屬數學指令之間沒有足夠的指令。為了讓我們的著色器編譯器更好地調度紋理指令,這個循環需要展開,所以我們的編譯器知道所有的紋理拾取都將被執行,并且可以決定如何調度它們(可能將多個紋理拾取組合在一起)嘗試最佳用獨立的數學指令覆蓋紋理指令的延遲。
在這種情況下,循環迭代次數(“c_S”)必須在FXC編譯時已知,而原始著色器中c_S是常量緩沖區值時不是這種情況。
“c_s”常量存儲在一個常量緩沖區中,但由于該值不會逐幀變化,因此可以為不同的c_s常量生成此像素著色器的排列,或者僅使用#define對該值進行硬編碼, 喜歡這個:
#if0floatc_S;#其他#definec_S15floatc_S_unused;#萬一現在c_S在FXC編譯時已知,for()循環可以使用[unroll] HLSL關鍵字完全展開,如下所示:
[unroll]for(inti=0;i度量新的價值舊值新舊GPU已用時間3.44毫秒4.25毫秒24%的收益頂部SOL [0]SM:81.2%SM:63.7%1.27倍頂部SOL [1]TEX:81.2%TEX:52.9%1.53xSM單元激活99.9%99.9%1.00倍每個經過周期的SM問題利用率74.4%63.7%1.17x每個活動周期的SM問題利用率74.5%63.8%1.17xSM入住率45.262.80.72xTEX命中率96.2%94.2%1.02XL2命中率85.6%91.5%0.94倍 表3.使用展開循環的新度量標準。
由于寄存器壓力增加,SM占用從每個活動周期的62.8到45.2有效彎曲下降:完全展開該循環導致更多的TEX指令同時執行,這會消耗更多寄存器來存儲TEX結果。盡管如此,“每次活動周期的SM問題利用率”指標為74.5%,接近80%,因此有更多的主動式經紗可能會稍微提高性能,但不會超過工作負荷的10%。
總體而言,兩項優化相結合,使工作負載的性能提高了47%(5.05至3.44毫秒)。并且,為了記錄,在退出早期退出分支后,這些優化會使工作負載(0.75到0.62 ms)獲得21%的增益。
附錄:優化Ray-Marching循環
如第6.2.2節所述(“減少SM問題 - 延遲延遲”),包含TEX指令的動態循環可能受到TEX指令的延遲以及沒有可以從相同的計劃調度的獨立指令的限制warp(沒有指令級并行性),并且SM中的活動warps數量不足以完全隱藏TEX延遲。
這種情況通常發生在光線漫游動態循環中,這些循環通常用于屏幕空間反射(SSR)著色器以及光線行進的體積照明。
在HLSL中,具有提前退出的典型SSR光線前進循環如下所示:
floatMinHitT=1.0;floatRayT=Jitter*Step+Step; [loop]for(inti=0;i通過部分展開循環2次并將紋理獲取指令背靠背放置在HLSL中,獨立紋理指令的批次可以并行執行,并且第二次獲取的延遲可以部分由延遲隱藏的第一個。
假設NumSteps是2的倍數,那么生成的HLSL看起來像這樣:
floatMinHitT=1.0;floatRayT=Jitter*Step+Step;[loop]for(inti=0;i通過在1607 Mhz的GTX 1080上以4K為單位的SSR測試應用程序進行上述優化,SSR工作負載所用的GPU時間從0.54 ms變為0.42 ms(工作負載加速29%)。通過進一步批量處理4個紋理,而不是2個,GPU時間下降到0.33 ms(工作負載加速64%:0.54 - > 0.33 ms /幀)。
-
NVIDIA
+關注
關注
14文章
4936瀏覽量
102814 -
gpu
+關注
關注
28文章
4700瀏覽量
128697
發布評論請先 登錄
相關推薦
評論