GPU架构 核心问题笔记
近日,笔者阅读学习了这篇详细介绍GPU架构的文章,实在受益匪浅。而文章的作者在开头提出了13个问题,笔者为了不让自己在学习后过快地遗忘,决定还是写一篇笔记记录所学,以供日后复习之用,顺便也向各位安利这篇好文。
*笔记中大部分的描述都取自原文章,以保证正确性。如果有部分内容存在理解错误,还请各位大佬指出。
*本笔记原发布于CSDN,转到知乎后可能存在双水印问题,还请各位多多包涵。
1、GPU是如何与CPU协调工作的?
CPU与GPU的交流通过MMIO(Memory Mapped IO)进行。CPU 通过 MMIO 访问 GPU 的寄存器状态。 任何命令都是由CPU发出。命令流(command stream)被提交到硬件单元,也就是GPU Channel。
CPU-GPU数据流
<hr/>2、GPU也有缓存机制吗?有几层?它们的速度差异多少?
有,某些GPU最多包含5层结构,分别为寄存器、L1缓存、L2缓存、GPU显存、系统显存。
以2010年推出的NVidia Fermi架构为例(L2缓存在左下图中)
<hr/>3、GPU的渲染流程有哪些阶段?它们的功能分别是什么?
顶点着色器:
[*]将顶点从模型空间转换到世界空间
[*]从世界空间转换到摄像机空间
[*]确定光线对材质的影响(Shading) *此时将信息储存,用于之后的逐片元计算
[*]进行投影(正交/透视),转换至裁剪坐标系/标准化设备坐标系(normalized device coordinates,即NDC)(所有坐标在-1到1之间)
曲面细分: 根据摄像机的距离,调整片面的数量。
几何着色器: 对输入的几何体进行一系列操作,使其变成另一种几何体,如将粒子转化为一个正方形面片(由两个三角形面片组成),以供之后渲染。
光栅化: 在此阶段,将计算三角形的微分、边方程和其他数据。这些数据可用于三角形遍历,以及几何阶段生成的各种阴影数据的插值
Early-Z: 在像素着色器之前进行深度测试,具体下一问会谈到。
像素着色器: 以从光栅化阶段所传来的顶点各值的插值进行各种计算、纹理采样
透明度测试: 即Alpha Test,若某片元的Alpha值不满足某条件,则直接将其舍弃。
模板测试: 即Stencil Testing
深度测试: 将被其他片元挡住的片元舍弃。
<hr/>4、Early-Z技术是什么?发生在哪个阶段?这个阶段还会发生什么?会产生什么问题?如何解决?
Early-Z技术:将深度测试提至像素着色器之前 Early-Z技术可以将很多无效的像素提前剔除,避免它们进入耗时严重的像素着色器。Early-Z剔除的最小单位不是1像素,而是像素块(2x2)
但是,以下情况会导致Early-Z失效:
[*]开启Alpha Test:由于Alpha Test需要在像素着色器后面的Alpha Test阶段比较,所以无法在像素着色器之前就决定该像素是否被剔除。
[*]开启Tex Kill:即在shader代码中有像素摒弃指令(DX的discard,OpenGL的clip)。
[*]在pixel shader中修改深度值。
[*]关闭深度测试。Early-Z是建立在深度测试看开启的条件下,如果关闭了深度测试,也就无法启用Early-Z技术。
///////////
感谢@GuardHei 指出原文章中的“开启Multi-Sampling会导致Early-Z失效”这一结论错误,已修改
///////////
Early-Z也会导致一个问题——深度数据冲突(depth data hazard)
假设数值深度值5已经经过Early-Z即将写入Frame Buffer,而深度值10刚好处于Early-Z阶段,读取并对比当前缓存的深度值15,结果就是10通过了Early-Z测试,会覆盖掉比自己小的深度值5避免深度数据冲突的方法之一是在写入深度值之前,再次与frame buffer的值进行对比
<hr/>5、SIMD和SIMT是什么?它们的好处是什么?co-issue呢?
SIMD:Single Instruction Multiple Data,单指令多数据。
SIMT:Single Instruction Multiple Threads,单指令多线程。是SIMD的升级版。可对GPU中单个SM中的多个Core同时处理同一指令,并且每个Core存取的数据可以是不同的。
co-issue是为了解决SIMD运算单元无法充分利用的问题。
<hr/>6、GPU是并行处理的么?若是,硬件层是如何设计和实现的?
当然是,而且是高度并行的。 仍旧以Fermi架构为例, 它拥有拥有16个SM,每个SM拥有2个Warp(线程束),每个Warp拥有16个Core,每个Core又有1个FPU(浮点数单元)以及1个ALU(逻辑运算单元)……
在获取数据之后,在SM中以32个线程为一组的线程束(Warp)来调度,来开始处理顶点数据。Warp是典型的单指令多线程(SIMT,SIMD单指令多数据的升级)的实现,也就是32个线程同时执行的指令是一模一样的,只是线程数据不一样,这样的好处就是一个Warp只需要一个套逻辑对指令进行解码和执行就可以了。也就实现了各个Warp之间的并行<hr/>7、GPC、TPC、SM是什么?Warp又是什么?它们和Core、Thread之间的关系如何?
GPC:图形处理簇,内含数个TPC
TPC:纹理处理簇,内含数个SM
SM:Stream Multiprocessor,流多处理器,内含数个Warp
Warp:线程束,内含数十个Core,而每个Core可以作为线程(Thread)的执行者。
Turing架构的GPU
<hr/>8、顶点着色器(VS)和像素着色器(PS)可以是同一处理单元吗?为什么?
可以,因为如今的GPU已经引入了统一着色器架构(Unified shader Architecture)。用了此架构的GPU,VS和PS用的都是相同的Core。也就是说,同一个Core既可以是VS又可以是PS。
<hr/>9、像素着色器(PS)的最小处理单位是1像素吗?为什么?会带来什么影响?
不是, 像素着色器中,会将相邻的四个像素作为不可分隔的一组,送入同一个SM内4个不同的Core
原作者推测有以下原因: 1、简化和加速像素分派的工作。 2、精简SM的架构,减少硬件单元数量和尺寸。 3、降低功耗,提高效能比。 4、无效像素虽然不会被存储结果,但可辅助有效像素求导函数。
同时,也会激化过绘制(Over Draw)的情况,损耗额外的性能
原本只需绘制三个像素,使用3个Core,但实际上这个三角形涉及到了3个像素块,因此需要使用12个Core来绘制,造成性能浪费
<hr/>10、Shader中的if、for等语句会降低渲染效率吗?为什么?
绝大部分情况下会降低,除非一个Warp中的所有线程都走进了同一分支或循环次数相等。
SM的warp调度器会按照顺序分发指令给整个warp,单个warp中的线程会锁步(lock-step)执行各自的指令,如果线程碰到不激活执行的情况也会被遮掩(be masked out)。 被遮掩的原因有很多,例如当前的指令是if(true)的分支,但是当前线程的数据的条件是false,或者循环的次数不一样(比如for循环次数n不是常量,或被break提前终止了但是别的还在走),因此在shader中的分支会显著增加时间消耗,在一个warp中的分支除非32个线程都走到if或者else里面,否则在进行其中一个分支时,走入另一个分支的wrap会阻塞而不进行任何操作,在时间开销上相当于所有的分支都走了一遍,线程不能独立执行指令而是以warp为单位,而这些warp之间才是独立的。感谢@烟雨迷离半世殇 指出这一段中加粗字体的措辞易产生歧义,已修改
<hr/>11、如下图,渲染相同面积的图形,三角形数量少(左)的还是数量多(右)的效率更快?为什么?
左边效率高,因为若同一个像素块如果分属不同的三角形,就会分配到不同的SM进行处理。由此推断,相同面积的区域,如果所属的三角形越多,就会导致分配给SM的次数越多,消耗的渲染性能也越多。
<hr/>12、GPU Context是什么?有什么作用?
GPU Context:- GPU Context代表了GPU计算的状态。- 在GPU中拥有自己的虚拟地址。- GPU 中可以并存多个活跃态下的Context。
由于SIMT技术的引入,导致很多同一个SM内的很多Core并不是独立的,当它们当中有部分Core需要访问到纹理、常量缓存和全局内存时,就会导致非常大的卡顿(Stall)。
例如下图中,有4组上下文(Context),它们共用同一组逻辑运算单元ALU。
延迟的后果是每组Context的总体执行时间被拉长了,但是,越多Context可用就越可以提升运算单元的吞吐量。
<hr/>13、造成渲染瓶颈的问题很可能有哪些?该如何避免或优化它们?
CPU和GPU的数据交换次数过多:
过绘制(Overdraw):
分支或循环、计算优化:
好文章 sm的warp那一块并不是所有分支都走一遍,这部分描述和rtr4里一致,都是错误的,应该是非此分支数据会导致当前处理单元处于阻塞状态
https://www.sciencedirect.com/topics/computer-science/thread-divergence
https://blog.csdn.net/junparadox/article/details/50541825
https://cvw.cac.cornell.edu/gpu/thread_div 我觉得文章的“相当于所有的分支都走了一遍”意思是说不同分支的处理单元阻塞,在时间开销上相当于分支都走了一次吧,应该跟你的观点不冲突才对 如果你理解的是“相当于所有的分支都走了一遍”的意思是没有执行分支的话,那确实是和我观点不冲突 事实上“相当于所有的分支都走了一遍”这种说法,很容易被误解为计算机操作系统中数据的条件转移操作 msaa导致earlyz失效在现在的gpu上还有吗?那depth prepass fwd岂不是也不能用msaa了?不对吧? 我查了下,应该是除非改了SV_Coverage,否则只是开了msaa应该不会导致earlyz失效,subsample也是会earlyz的 你是对的,我也找不到其他能支持“MSAA会导致early-z失效”这一结论的资料。大半年前啥都不懂时做的笔记现在回头看确实能发现一些问题,还有文中提到的Alpha Blend也是一大迷惑点。 您好,请问 12 条 GPU Context 那里的图出处是哪里呢? 我理解的这个图应该指的是 SM 内部多个 Warp 执行的方式,而不是 GPU Context 的并发执行模式。不同 GPU Context 目前应该只能 time-slice sharing 吧?
页:
[1]
2