深入GPU硬件架構(gòu)及運行機制(下)


一、導(dǎo)言
二、GPU概述
三、GPU物理架構(gòu)
四、GPU運行機制
4.1 GPU渲染總覽
4.2 GPU邏輯管線
4.3 GPU技術(shù)要點
4.4 GPU資源機制
4.4.1 內(nèi)存架構(gòu)
4.4.2 GPU Context和延遲
4.4.3 CPU-GPU異構(gòu)系統(tǒng)
4.4.4 GPU資源管理模型
4.4.5 CPU-GPU數(shù)據(jù)流
4.4.6 顯像機制
4.5 Shader運行機制
4.6 利用擴展例證
五、總結(jié)
5.1 CPU vs GPU
5.2 渲染優(yōu)化建議
5.3 GPU的未來
5.4 結(jié)語
參考文獻
特別說明
上篇:深入GPU硬件架構(gòu)及運行機制(上)
4.4 GPU資源機制
4.4.1 內(nèi)存架構(gòu)


4.4.2 GPU Context和延遲





4.4.3 CPU-GPU異構(gòu)系統(tǒng)

4.4.4 GPU資源管理模型

MMIO(Memory Mapped IO) CPU與GPU的交流就是通過MMIO進行的。CPU 通過 MMIO 訪問 GPU 的寄存器狀態(tài)。 DMA傳輸大量的數(shù)據(jù)就是通過MMIO進行命令控制的。 I/O端口可用于間接訪問MMIO區(qū)域,像Nouveau等開源軟件從來不訪問它。 GPU Context GPU Context代表了GPU計算的狀態(tài)。 在GPU中擁有自己的虛擬地址。 GPU 中可以并存多個活躍態(tài)下的Context。 GPU Channel 任何命令都是由CPU發(fā)出。 命令流(command stream)被提交到硬件單元,也就是GPU Channel。 每個GPU Channel關(guān)聯(lián)一個context,而一個GPU Context可以有多個GPU channel。 每個GPU Context 包含相關(guān)channel的 GPU Channel Descriptors , 每個 Descriptor 都是 GPU 內(nèi)存中的一個對象。 每個 GPU Channel Descriptor 存儲了 Channel 的設(shè)置,其中就包括 Page Table 。 每個 GPU Channel 在GPU內(nèi)存中分配了唯一的命令緩存,這通過MMIO對CPU可見。 GPU Context Switching 和命令執(zhí)行都在GPU硬件內(nèi)部調(diào)度。 GPU Page Table GPU Context在虛擬基地空間由Page Table隔離其它的Context 。 GPU Page Table隔離CPU Page Table,位于GPU內(nèi)存中。 GPU Page Table的物理地址位于 GPU Channel Descriptor中。 GPU Page Table不僅僅將 GPU虛擬地址轉(zhuǎn)換成GPU內(nèi)存的物理地址,也可以轉(zhuǎn)換成CPU的物理地址。因此,GPU Page Table可以將GPU虛擬地址和CPU內(nèi)存地址統(tǒng)一到GPU統(tǒng)一虛擬地址空間來。 PCI-e BAR GPU 設(shè)備通過PCI-e總線接入到主機上。Base Address Registers(BARs) 是 MMIO的窗口,在GPU啟動時候配置。 GPU的控制寄存器和內(nèi)存都映射到了BARs中。 GPU設(shè)備內(nèi)存通過映射的MMIO窗口去配置GPU和訪問GPU內(nèi)存。 PFIFO Engine PFIFO是GPU命令提交通過的一個特殊的部件。 PFIFO維護了一些獨立命令隊列,也就是Channel。 此命令隊列是Ring Buffer,有PUT和GET的指針。 所有訪問Channel控制區(qū)域的執(zhí)行指令都被PFIFO 攔截下來。 GPU驅(qū)動使用Channel Descriptor來存儲相關(guān)的Channel設(shè)定。 PFIFO將讀取的命令轉(zhuǎn)交給PGRAPH Engine。 BO Buffer Object (BO),內(nèi)存的一塊(Block),能夠用于存儲紋理(Texture)、渲染目標(Render Target)、著色代碼(shader code)等等。 Nouveau和Gdev經(jīng)常使用BO。 Nouveau是一個自由及開放源代碼顯卡驅(qū)動程序,是為NVidia的顯卡所編寫。 Gdev是一套豐富的開源軟件,用于NVIDIA的GPGPU技術(shù),包括設(shè)備驅(qū)動程序。
4.4.5 CPU-GPU數(shù)據(jù)流

4.4.6 顯像機制
水平和垂直同步信號 在早期的CRT顯示器,電子槍從上到下逐行掃描,掃描完成后顯示器就呈現(xiàn)一幀畫面。然后電子槍回到初始位置進行下一次掃描。為了同步顯示器的顯示過程和系統(tǒng)的視頻控制器,顯示器會用硬件時鐘產(chǎn)生一系列的定時信號。 
當電子槍換行進行掃描時,顯示器會發(fā)出一個水平同步信號(horizonal synchronization),簡稱 HSync 當一幀畫面繪制完成后,電子槍回復(fù)到原位,準備畫下一幀前,顯示器會發(fā)出一個垂直同步信號(vertical synchronization),簡稱 VSync。 顯示器通常以固定頻率進行刷新,這個刷新率就是 VSync 信號產(chǎn)生的頻率。雖然現(xiàn)在的顯示器基本都是液晶顯示屏了,但其原理基本一致。 CPU將計算好顯示內(nèi)容提交至 GPU,GPU 渲染完成后將渲染結(jié)果存入幀緩沖區(qū),視頻控制器會按照 VSync 信號逐幀讀取幀緩沖區(qū)的數(shù)據(jù),經(jīng)過數(shù)據(jù)轉(zhuǎn)換后最終由顯示器進行顯示。 
雙緩沖 在單緩沖下,幀緩沖區(qū)的讀取和刷新都都會有比較大的效率問題,經(jīng)常會出現(xiàn)相互等待的情況,導(dǎo)致幀率下降。 為了解決效率問題,GPU 通常會引入兩個緩沖區(qū),即 雙緩沖機制。在這種情況下,GPU 會預(yù)先渲染一幀放入一個緩沖區(qū)中,用于視頻控制器的讀取。當下一幀渲染完畢后,GPU 會直接把視頻控制器的指針指向第二個緩沖器。 
垂直同步 雙緩沖雖然能解決效率問題,但會引入一個新的問題。當視頻控制器還未讀取完成時,即屏幕內(nèi)容剛顯示一半時,GPU 將新的一幀內(nèi)容提交到幀緩沖區(qū)并把兩個緩沖區(qū)進行交換后,視頻控制器就會把新的一幀數(shù)據(jù)的下半段顯示到屏幕上,造成畫面撕裂現(xiàn)象: 
為了解決這個問題,GPU 通常有一個機制叫做垂直同步(簡寫也是V-Sync),當開啟垂直同步后,GPU 會等待顯示器的 VSync 信號發(fā)出后,才進行新的一幀渲染和緩沖區(qū)更新。這樣能解決畫面撕裂現(xiàn)象,也增加了畫面流暢度,但需要消費更多的計算資源,也會帶來部分延遲。
4.5 Shader運行機制


sampler mySamp;
Texture2D<float3> myTex;
float3 lightDir;
float4 diffuseShader(float3 norm, float2 uv)
{
float3 kd;
kd = myTex.Sample(mySamp, uv);
kd *= clamp( dot(lightDir, norm), 0.0, 1.0);
return float4(kd, 1.0);
}
<diffuseShader>:
sample r0, v4, t0, s0
mul r3, v0, cb0[0]
madd r3, v1, cb0[1], r3
madd r3, v2, cb0[2], r3
clmp r3, r3, l(0.0), l(1.0)
mul o0, r0, r3
mul o1, r1, r3
mul o2, r2, r3
mov o3, l(1.0)


<VEC8_diffuseShader>:
VEC8_sample vec_r0, vec_v4, t0, vec_s0
VEC8_mul vec_r3, vec_v0, cb0[0]
VEC8_madd vec_r3, vec_v1, cb0[1], vec_r3
VEC8_madd vec_r3, vec_v2, cb0[2], vec_r3
VEC8_clmp vec_r3, vec_r3, l(0.0), l(1.0)
VEC8_mul vec_o0, vec_r0, vec_r3
VEC8_mul vec_o1, vec_r1, vec_r3
VEC8_mul vec_o2, vec_r2, vec_r3
VEC8_mov o3, l(1.0)


4.6 利用擴展例證
OpenGL 4.3+; GLSL 4.3+; 支持OpenGL 4.3+的NV顯卡;
This extension interacts with NV_gpu_program5
This extension interacts with NV_compute_program5
This extension interacts with NV_tessellation_program5
// 開啟擴展
#extension GL_NV_shader_thread_group : require (or enable)
WARP_SIZE_NV // 單個線程束的線程數(shù)量
WARPS_PER_SM_NV // 單個SM的線程束數(shù)量
SM_COUNT_NV // SM數(shù)量
uniform uint gl_WarpSizeNV; // 單個線程束的線程數(shù)量
uniform uint gl_WarpsPerSMNV; // 單個SM的線程束數(shù)量
uniform uint gl_SMCountNV; // SM數(shù)量
in uint gl_WarpIDNV; // 當前線程束id
in uint gl_SMIDNV; // 當前線程束所在的SM id,取值[0, gl_SMCountNV-1]
in uint gl_ThreadInWarpNV; // 當前線程id,取值[0, gl_WarpSizeNV-1]
in uint gl_ThreadEqMaskNV; // 是否等于當前線程id的位域掩碼。
in uint gl_ThreadGeMaskNV; // 是否大于等于當前線程id的位域掩碼。
in uint gl_ThreadGtMaskNV; // 是否大于當前線程id的位域掩碼。
in uint gl_ThreadLeMaskNV; // 是否小于等于當前線程id的位域掩碼。
in uint gl_ThreadLtMaskNV; // 是否小于當前線程id的位域掩碼。
in bool gl_HelperThreadNV; // 當前線程是否協(xié)助型線程。
gl_HelperThreadNV是指在處理2x2的像素塊時,那些未被圖元覆蓋的像素著色器線程將被標記為gl_HelperThreadNV = true,它們的結(jié)果將被忽略,也不會被存儲,但可輔助一些計算,如導(dǎo)數(shù)dFdx和dFdy。為了防止理解有誤,貼出原文:The variable gl_HelperThreadNV specifies if the current thread is a helper thread. In implementations supporting this extension, fragment shader invocations may be arranged in SIMD thread groups of 2x2 fragments called "quad". When a fragment shader instruction is executed on a quad, it\\\'s possible that some fragments within the quad will execute the instruction even if they are not covered by the primitive. Those threads are called helper threads. Their outputs will be discarded and they will not execute global store functions, but the intermediate values they compute can still be used by thread group sharing functions or by fragment derivative functions like dFdx and dFdy.
操作系統(tǒng):Windows 10 Pro, 64-bit DirectX 版本:12.0
GPU 處理器:GeForce RTX 2060
驅(qū)動程序版本:417.71
Driver Type: Standard
Direct3D API 版本:12
Direct3D 功能級別:12_1CUDA 核心:1920
核心時鐘:1710 MHz
內(nèi)存數(shù)據(jù)速率:14.00 Gbps
內(nèi)存接口:192-位
內(nèi)存帶寬:336.05 GB/秒
全部可用的圖形內(nèi)存:22494MB
專用視頻內(nèi)存:6144 MB GDDR6
系統(tǒng)視頻內(nèi)存:0MB
共享系統(tǒng)內(nèi)存:16350MB
視頻 BIOS 版本:90.06.3F.00.73
IRQ:Not used
總線:PCI Express x16 Gen3
// set up vertex data (and buffer(s)) and configure vertex attributes
const float HalfSize = 1.0f;
float vertices[] = {
-HalfSize, -HalfSize, 0.0f, // left bottom
HalfSize, -HalfSize, 0.0f, // right bottom
-HalfSize, HalfSize, 0.0f, // top left
-HalfSize, HalfSize, 0.0f, // top left
HalfSize, -HalfSize, 0.0f, // right bottom
HalfSize, HalfSize, 0.0f, // top right
};
#version 430 core
layout (location = 0) in vec3 aPos;
void main()
{
gl_Position = vec4(aPos, 1.0f);
}
#version 430 core
out vec4 FragColor;
void main()
{
FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
#version 430 core
#extension GL_NV_shader_thread_group : require
uniform uint gl_WarpSizeNV; // 單個線程束的線程數(shù)量
uniform uint gl_WarpsPerSMNV; // 單個SM的線程束數(shù)量
uniform uint gl_SMCountNV; // SM數(shù)量
in uint gl_WarpIDNV; // 當前線程束id
in uint gl_SMIDNV; // 當前線程所在的SM id,取值[0, gl_SMCountNV-1]
in uint gl_ThreadInWarpNV; // 當前線程id,取值[0, gl_WarpSizeNV-1]
out vec4 FragColor;
void main()
{
// SM id
float lightness = gl_SMIDNV / gl_SMCountNV;
FragColor = vec4(lightness);
}
畫面共有32個亮度色階,也就是Geforce RTX 2060有32個SM。 單個SM每次渲染16x16為單位的像素塊,也就是每個SM有256個Core。 SM之間不是順序分配像素塊,而是無序分配。 不同三角形的接縫處出現(xiàn)斷層,說明同一個像素塊如果分屬不同的三角形,就會分配到不同的SM進行處理。由此推斷,相同面積的區(qū)域,如果所屬的三角形越多,就會導(dǎo)致分配給SM的次數(shù)越多,消耗的渲染性能也越多。
// warp id
float lightness = gl_WarpIDNV / gl_WarpsPerSMNV;
FragColor = vec4(lightness);
畫面共有32個亮度色階,也就是每個SM有32個Warp,每個Warp有8個Core。 每個色塊像素是4x8,由于每個Warp有8個Core,由此推斷每個Core單次要處理2x2的最小單元像素塊。 也是無序分配像素塊。 三角形接縫處出現(xiàn)斷層,同SM的推斷一致。
// thread id
float lightness = gl_ThreadInWarpNV / gl_WarpSizeNV;
FragColor = vec4(lightness);
相較SM、線程束,線程分布圖比較規(guī)律。說明同一個Warp的線程分布是規(guī)律的。 三角形接縫處出現(xiàn)紊亂,說明是不同的Warp造成了不同的線程。 畫面有32個色階,說明單個Warp有32個線程。 每個像素獨占一個亮度色階,與周邊相鄰像素都不同,說明每個線程只處理一個像素。
五、總結(jié)
5.1 CPU vs GPU

5.2 渲染優(yōu)化建議
減少CPU和GPU的數(shù)據(jù)交換: 例如: glGetUniformLocation會從GPU內(nèi)存查詢狀態(tài),耗費很多時間周期。避免每幀設(shè)置、查詢渲染狀態(tài),可在初始化時緩存狀態(tài)。 CPU版的粒子、動畫會每幀修改、提交數(shù)據(jù),可移至GPU端。 BVH Portal BSP OSP 合批(Batch) 減少頂點數(shù)、三角形數(shù) 視錐裁剪 避免每幀提交Buffer數(shù)據(jù) 減少渲染狀態(tài)設(shè)置和查詢 啟用GPU Instance 開啟LOD 避免從顯存讀數(shù)據(jù) 減少過繪制: 粒子數(shù)量多且面積小,由于像素塊機制,會加劇過繪制情況 植物、沙石、毛發(fā)等也如此 背面裁剪 遮擋裁剪 視口裁剪 剪切矩形(scissor rectangle) Early-Z 層次Z緩沖(Hierarchical Z-Buffering,HZB) 避免Tex Kill操作 避免Alpha Test 避免Alpha Blend 開啟深度測試 開啟裁剪: 控制物體數(shù)量 Shader優(yōu)化: 避免if、switch分支語句 避免 for循環(huán)語句,特別是循環(huán)次數(shù)可變的減少紋理采樣次數(shù) 禁用 clip或discard操作減少復(fù)雜數(shù)學(xué)函數(shù)調(diào)用
移動游戲性能優(yōu)化通用技法。 GPU Programming Guide。 Real-Time Rendering Resources。
5.3 GPU的未來
硬件升級。更多運算單元,更多存儲空間,更高并發(fā),更高帶寬,更低延時。。。 Tile-Based Rendering的集成?;谕咂匿秩究梢砸欢ǔ潭冉档蛶捄吞嵘庹沼嬎阈?,目前部分移動端及桌面的GPU已經(jīng)引入這個技術(shù),未來將有望成為常態(tài)。 3D內(nèi)存技術(shù)。目前大多數(shù)傳統(tǒng)的內(nèi)存是2D的,3D內(nèi)存則不同,在物理結(jié)構(gòu)上是3D的,類似立方體結(jié)構(gòu),集成于芯片內(nèi)。可獲得幾倍的訪問速度和效能比。 
GPU愈加可編程化。GPU天生是并行且相對固定的,未來將會開放越來越多的shader可供編程,而CPU剛好相反,將往并行化發(fā)展。也就是說,未來的GPU越來越像CPU,而CPU越來越像GPU。難道它們應(yīng)驗了古語:合久必分,分久必合么? 
實時光照追蹤的普及?;赥uring架構(gòu)的GPU已經(jīng)加入大量RT Core、HVB、AI降噪等技術(shù),Hybrid Rendering Pipeline就是此架構(gòu)的光線追蹤渲染管線,能夠同時結(jié)合光柵化器、RT Core、Compute Core執(zhí)行混合渲染: 
Hybrid Rendering Pipeline相當于光線追蹤渲染管線和光柵化渲染管線的合體: 
數(shù)據(jù)并發(fā)提升、深度神經(jīng)網(wǎng)絡(luò)、GPU計算單元等普及及提升。 
AI降噪和AI抗鋸齒。AI降噪已經(jīng)在部分RTX系列的光線追蹤版本得到應(yīng)用,而AI抗鋸齒(Super Res)可用于超高分辨率的視頻圖像抗鋸齒: 
基于任務(wù)和網(wǎng)格著色器的渲染管線。基于任務(wù)和網(wǎng)格著色器的渲染管線(Graphics Pipeline with Task and Mesh Shaders)與傳統(tǒng)的光柵化渲染光線有著很大的差異,它以線程組(Thread Group)、任務(wù)著色器(Task shader)和網(wǎng)格著色器(Mesh shader)為基礎(chǔ),形成一種全新的渲染管線: 
關(guān)于此技術(shù)的更多詳情可閱讀:NVIDIA Turing Architecture Whitepaper。 可變速率著色(Variable Rate Shading)??勺兝手夹g(shù)可判斷畫面區(qū)域的重要性(或由應(yīng)用程序指定),然后根據(jù)畫面區(qū)域的重要性程度采用不同的著色分辨率精度,可以顯著降低功耗,提高著色效率。

5.4 結(jié)語
如果想更深入地了解GPU的設(shè)計細節(jié)、實現(xiàn)細節(jié),可閱讀GPU廠商定期發(fā)布的白皮書和各大高校、機構(gòu)發(fā)布的論文。推薦一個GPU解說視頻:A trip through the Graphics Pipeline 2011: Index,雖然是多年前的視頻,但比較系統(tǒng)、全面地講解了GPU的機制和技術(shù)。
作者:0向往0
博客地址:
https://www.cnblogs.com/timlly/p/11471507.html
Real-Time Rendering Resources Life of a triangle - NVIDIA\\'s logical pipeline NVIDIA Pascal Architecture Whitepaper NVIDIA Turing Architecture Whitepaper Pomegranate: A Fully Scalable Graphics Architecture Performance Optimization Guidelines and the GPU Architecture behind them A trip through the Graphics Pipeline 2011 Graphic Architecture introduction and analysis Exploring the GPU Architecture Introduction to GPU Architecture An Introduction to Modern GPU Architecture GPU TECHNOLOGY: PAST, PRESENT, FUTURE GPU Computing & Architectures NVIDIA VOLTA NVIDIA TURING Graphics processing unit GPU并行架構(gòu)及渲染優(yōu)化 渲染優(yōu)化-從GPU的結(jié)構(gòu)談起 GPU Architecture and Models Introduction to and History of GPU Algorithms GPU Architecture Overview 計算機那些事(8)——圖形圖像渲染原理 GPU Programming Guide GeForce 8 and 9 Series GPU的工作原理 NVIDIA顯示核心列表 DirectX 高級著色器語言 探究光線追蹤技術(shù)及UE4的實現(xiàn) 移動游戲性能優(yōu)化通用技法 NV shader thread group 實時渲染深入探究 NVIDIA GPU 硬件介紹 Data Transfer Matters for GPU Computing Slang – A Shader Compilation System Graphics Shaders - Theory and Practice 2nd Edition
本號資料全部上傳至知識星球,更多內(nèi)容請登錄智能計算芯知識(知識星球)星球下載全部資料。

免責申明:本號聚焦相關(guān)技術(shù)分享,內(nèi)容觀點不代表本號立場,可追溯內(nèi)容均注明來源,發(fā)布文章若存在版權(quán)等問題,請留言聯(lián)系刪除,謝謝。
電子書<服務(wù)器基礎(chǔ)知識全解(終極版)>更新完畢,知識點深度講解,提供182頁完整版下載。
溫馨提示:
請搜索“AI_Architect”或“掃碼”關(guān)注公眾號實時掌握深度技術(shù)分享,點擊“閱讀原文”獲取更多原創(chuàng)技術(shù)干貨。

