GPU架构 核心问题记录

原文:深入GPU硬件架构及运行机制

1、GPU是如何与CPU协调工作的?

CPU与GPU的交流通过MMIO(Memory Mapped IO)进行。CPU 通过 MMIO 访问 GPU 的寄存器状态。
任何命令都是由CPU发出。命令流(command stream)被提交到硬件单元,也就是GPU Channel。
GPU架构 核心问题记录_第1张图片
GPU架构 核心问题记录_第2张图片

CPU-GPU数据流

2、GPU也有缓存机制吗?有几层?它们的速度差异多少?

有,某些GPU最多包含5层结构,分别为寄存器、L1缓存、L2缓存、GPU显存、系统显存。
GPU架构 核心问题记录_第3张图片

GPU架构 核心问题记录_第4张图片

以2010年推出的NVidia Fermi架构为例(L2缓存在左下图中)
GPU架构 核心问题记录_第5张图片


3、GPU的渲染流程有哪些阶段?它们的功能分别是什么?

GPU架构 核心问题记录_第6张图片
顶点着色器:

  1. 将顶点从模型空间转换到世界空间
  2. 从世界空间转换到摄像机空间
  3. 确定光线对材质的影响(Shading)
    *此时将信息储存,用于之后的逐片元计算
  4. 进行投影(正交/透视),转换至裁剪坐标系/标准化设备坐标系(normalized device coordinates,即NDC)(所有坐标在-1到1之间)

曲面细分:
根据摄像机的距离,调整片面的数量。

几何着色器:
对输入的几何体进行一系列操作,使其变成另一种几何体,如将粒子转化为一个正方形面片(由两个三角形面片组成),以供之后渲染。

光栅化
在此阶段,将计算三角形的微分、边方程和其他数据。这些数据可用于三角形遍历,以及几何阶段生成的各种阴影数据的插值

Early-Z
在像素着色器之前进行深度测试,具体下一问会谈到。

像素着色器
以从光栅化阶段所传来的顶点各值的插值进行各种计算、纹理采样

透明度测试
即Alpha Test,若某片元的Alpha值不满足某条件,则直接将其舍弃。

模板测试
即Stencil Testing

深度测试:
将被其他片元挡住的片元舍弃。


4、Early-Z技术是什么?发生在哪个阶段?这个阶段还会发生什么?会产生什么问题?如何解决?

Early-Z技术:将深度测试提至像素着色器之前
Early-Z技术可以将很多无效的像素提前剔除,避免它们进入耗时严重的像素着色器。Early-Z剔除的最小单位不是1像素,而是像素块(2x2)

但是,以下情况会导致Early-Z失效:

  • 开启Alpha Test:由于Alpha Test需要在像素着色器后面的Alpha Test阶段比较,所以无法在像素着色器之前就决定该像素是否被剔除。
  • 开启Alpha Blend:启用了Alpha混合的像素很多需要与frame buffer做混合,无法执行深度测试,也就无法利用Early-Z技术。
  • 开启Tex Kill:即在shader代码中有像素摒弃指令(DX的discard,OpenGL的clip)。
  • 关闭深度测试。Early-Z是建立在深度测试看开启的条件下,如果关闭了深度测试,也就无法启用Early-Z技术。
  • 开启Multi-Sampling:多采样会影响周边像素,而Early-Z阶段无法得知周边像素是否被裁剪,故无法提前剔除。
  • 以及其它任何导致需要混合后面颜色的操作。

Early-Z也会导致一个问题——深度数据冲突(depth data hazard)

假设数值深度值5已经经过Early-Z即将写入Frame Buffer,而深度值10刚好处于Early-Z阶段,读取并对比当前缓存的深度值15,结果就是10通过了Early-Z测试,会覆盖掉比自己小的深度值5

避免深度数据冲突的方法之一是在写入深度值之前,再次与frame buffer的值进行对比


5、SIMD和SIMT是什么?它们的好处是什么?co-issue呢?

SIMD:Single Instruction Multiple Data,单指令多数据。
GPU架构 核心问题记录_第7张图片

SIMT:Single Instruction Multiple Threads,单指令多线程。是SIMD的升级版。可对GPU中单个SM中的多个Core同时处理同一指令,并且每个Core存取的数据可以是不同的。
GPU架构 核心问题记录_第8张图片
co-issue是为了解决SIMD运算单元无法充分利用的问题。
GPU架构 核心问题记录_第9张图片


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之间的并行


7、GPC、TPC、SM是什么?Warp又是什么?它们和Core、Thread之间的关系如何?

GPC:图形处理簇,内含数个TPC
TPC:纹理处理簇,内含数个SM
SM:Stream Multiprocessor,流多处理器,内含数个Warp
Warp:线程束,内含数十个Core,而每个Core可以作为线程的执行者。

GPU架构 核心问题记录_第10张图片

Turing架构的GPU

8、顶点着色器(VS)和像素着色器(PS)可以是同一处理单元吗?为什么?

可以,因为如今的GPU已经引入了统一着色器架构(Unified shader Architecture)。用了此架构的GPU,VS和PS用的都是相同的Core。也就是说,同一个Core既可以是VS又可以是PS。


9、像素着色器(PS)的最小处理单位是1像素吗?为什么?会带来什么影响?

不是,
像素着色器中,会将相邻的四个像素作为不可分隔的一组,送入同一个SM内4个不同的Core

原作者推测有以下原因:
1、简化和加速像素分派的工作。
2、精简SM的架构,减少硬件单元数量和尺寸。
3、降低功耗,提高效能比。
4、无效像素虽然不会被存储结果,但可辅助有效像素求导函数。

同时,也会激化过绘制(Over Draw)的情况,损耗额外的性能
GPU架构 核心问题记录_第11张图片
原本只需绘制三个像素,使用3个Core,但实际上这个三角形涉及到了3个像素块,因此需要使用12个Core来绘制,造成性能浪费
GPU架构 核心问题记录_第12张图片


10、Shader中的if、for等语句会降低渲染效率吗?为什么?

绝大部分情况下会降低,除非一个Warp中的所有线程都走进了同一分支或循环次数相等。
GPU架构 核心问题记录_第13张图片

SM的warp调度器会按照顺序分发指令给整个warp,单个warp中的线程会锁步(lock-step)执行各自的指令,如果线程碰到不激活执行的情况也会被遮掩(be masked out)。
被遮掩的原因有很多,例如当前的指令是if(true)的分支,但是当前线程的数据的条件是false,或者循环的次数不一样(比如for循环次数n不是常量,或被break提前终止了但是别的还在走),因此在shader中的分支会显著增加时间消耗,在一个warp中的分支除非32个线程都走到if或者else里面,否则相当于所有的分支都走了一遍,线程不能独立执行指令而是以warp为单位,而这些warp之间才是独立的。


11、如下图,渲染相同面积的图形,三角形数量少(左)的还是数量多(右)的效率更快?为什么?

GPU架构 核心问题记录_第14张图片
左边效率高,因为若同一个像素块如果分属不同的三角形,就会分配到不同的SM进行处理。由此推断,相同面积的区域,如果所属的三角形越多,就会导致分配给SM的次数越多,消耗的渲染性能也越多


12、GPU Context是什么?有什么作用?

GPU Context

  • GPU Context代表了GPU计算的状态
  • 在GPU中拥有自己的虚拟地址。
  • GPU 中可以并存多个活跃态下的Context。

由于SIMT技术的引入,导致很多同一个SM内的很多Core并不是独立的,当它们当中有部分Core需要访问到纹理、常量缓存和全局内存时,就会导致非常大的卡顿(Stall)。

例如下图中,有4组上下文(Context),它们共用同一组逻辑运算单元ALU。
GPU架构 核心问题记录_第15张图片
延迟的后果是每组Context的总体执行时间被拉长了,但是,越多Context可用就越可以提升运算单元的吞吐量


13、造成渲染瓶颈的问题很可能有哪些?该如何避免或优化它们?

CPU和GPU的数据交换次数过多:
GPU架构 核心问题记录_第16张图片

过绘制(Overdraw):
GPU架构 核心问题记录_第17张图片

分支或循环、计算优化:
GPU架构 核心问题记录_第18张图片

你可能感兴趣的:(笔记,图形学)