集成GPU vs. 独立GPU
独立GPU:
1.显卡内的RAM被GPU专用,不占用系统内存;
2.特点:功耗高,性能强劲;
3.连接方式:北桥上的内存连接GPU内存,再连接GPU。
集成GPU:
1.集成在主板或CPU上的GPU,运行时会占用系统内存;
2.从2009年开始,GPU已经从主板移至CPU,成为“核芯显卡”;
3.特点:功耗低,访存宽带受限;
4.连接方式:直接在北桥上,内存直接连接GPU。
移动GPU:
1.功耗是设计首要考虑问题;
2.架构和上面两种有差异。

GPU演进之路:
1.之前的GPGPU一般用于渲染计算,要利用GPU的并行计算能力必须通过图形API接口传输数据,开发门槛很高;
2.CUDA:通用计算平台,把GPU视为数据并行计算的设备;
3.统一编程单元:Vetex和Fragment处理单元分离,容易造成负载不均衡,从D3D10开始GPU开始使用统一单元运行Vertex、Fragment以及Geomerty Shader。
4.浮点计算标准化:精度和准确地向IEEE 754标准要求靠拢。
总结:GPU逐渐成为通用计算平台、大规模并行计算的主力军。

GPU vs. CPU
1.GPU为并行而设计,更重视整体Throughput;CPU为串行而设计,更看重任务间的Latency。
2.设计思路上,GPU将更多的晶体管用于计算单元(core),CPU讲更多的晶体管用于控制器和L1 cache。

费林分类法:
资讯流可分为指令(Instruction)和资料(Data)两种,分4中传输模式:
1.单一指令流单一数据流计算机(SISD, Single Instruction Single Data),如单核CPU,每次一条指令读取一个资料;
2.单一指令流多数据流计算机(SIMD, Single Instruction Multiple Data),如传统CPU的指令扩展SSE和NEON,每次指令可读取4个资料;
3.多指令流单一数据流计算机(MISD, Multiple Instruction Single Data);
4.多指令流多数据流计算机(MIMD, Multiple Instruction Multiple Data),如多核CPU,每次多条指令读取多个资料。

SIMT:现代GPU基于SIMD发展出的并行架构,以Nvida CUDA为例:
GPC->SM->CUDA Cor(SP)
GPC(也叫TPC):集群,一个集群上有1个Textrue Unit和2个SM;
Textrue Unit:纹理单元,一个纹理单元可以获取一张纹理;
SM:多处理器,上面有多个CUDA核;
CUDA Core:每个核跑一个线程即SP。

1.(硬件上)一个GPU Unit上有很多SM(Streaming Multiprocesso) --(软件上)Grid;
2.(硬件上)一个SM上有很多SP(Streaming Processor,即CUDA core) --(软件上)Block,多个SP共享内存和Caches Registers;
3.(硬件上)一个SP -- (软件上)一个Thread;
4.在GPU中的执行程序被称为Kernel(如vecAdd),一个Kernel指令下来所有的线程都执行相同的程序;
5.实际执行过程中,线程会被组装到Block中,并分配给SM进行计算;
6. 在硬件内部,Block进一步会被为分组成Warp,Warp是GPU硬件最小调度单位,Warp内的线程被一一分配给SP按照SIMD的模式工作,也就是这些线程共享同样的PC(程序计数器),以锁步(Lockstep)的方式执行指令。

SIMD vs. SMIT
SIMD:1个核上的寄存器可以存4个(受限于ALU的宽度)数据,4个同时去除,进行计算,在1个线程中进行,仅包含基础算数操作(加减乘除/绝对值/平方根),多用于CPU;
SMIT:4个核上,每个核分别进行4个(不受限)计算,4个线程并行执行,每个核有独立的寄存器、ALU、data cache,却共享instruction cache、编码器、Program Counter register,多用于GPU。

GPU和CPU并行能力对比:
GPU:以Fermi GF100为例,共有16个SM,每个SM可容纳48个Warp,每个Warp可容纳32个线程,整个GPU可支持24576个线程同时在线;
CPU:8核CPU,在打开Hyperthreading的情况下,只能同时支持十几个硬件线程同时在线。

GPU和CPU避免高延迟指令引起处理单元流水线停顿的做法对比:
GPU:频繁切换到别的线程Warp来规避指令延迟带来处理单元的停顿;
CPU:穷尽指令集规避+通过各级cache掩盖访问内存延迟,万不得已不切换到别的硬件线程。

GPU和CPU内存模型对比:
GPU:各级cache容量小(甚至没有
),Throughput大,Latency大;
CPU:各级cache容量大,Throughput小,Latency小;

带宽(Bandwidth):
1.每个时钟周期,GPU与一个VRAM之间总线可以传输的数据大小(位);
2.GPU的带宽一般比CPU大一个数量级;
3.指令带宽:每条指令平均获得内存访问数据大小,用来衡量单core吞吐能力,CPU和GUP指令带宽对比:
MOS 6502(CPU):4B
Core i7-7700K(CPU):1B
Core i7-7700K(CPU)(SIMD):0.125B
NVidia GeForce GTX 1080Ti(GPU):0.09B
4.延迟
GPU内存带宽:
GPU与显存之间的吞吐量,与数据频率(显存频率*倍率)和显存位宽(总线IO位宽)相关。
GPU带宽大小计算方式:
带宽(Bandwidth) = 数据频率(Transactions/Pin) * 位(总线)宽(Bus Width) / 8
GDDR5 128 GB/s = 8GT/s * 128-bit / 8
HBM 256 GB/s = 1GT/s * 2048-bit / 8

CPU->GPU数据全流程:
1.内存->CPU;
2.CPU->显存,通过数据总线,高延迟,带宽限制;(短板)
3.显存->GPU,超高并发。
总结:
1.尽量减少CPU和GPU之间的数据传输;
2.尽量避免“冯诺依曼架构瓶颈”,即数据和指令混在一起传给寄存器,很可能导致计算过程中CPU/GPU在缓存中找不到数据(cache miss),从而需要从内存中读取数据,造成多次Latency。

--------------------------------

历代各GPU架构

Tesla架构
【【【整体架构】】】
【Host CPU】 甲方大大
【GPU】 卑微外包公司,干各种又脏又累的活
【Host Interface】“对外负责人”,负责收发来自CPU的指令、上下文切换、把内存数据放到显存中
【Input Assembler】简单组装,传给Vetex Work Distribution
【Vertex/Pixel/Compute Work Distribution】三个“小包工头”,负责Vertex/Pixel/Compute任务精细组装
【TPC/GPC】一个个“工厂”,负责所有图形计算,包含1个Texture unit和2个SM
【Viewport/clip/setup/raster/zcull block】负责顶点着色器处理完后的,负责视口变换、裁剪、属性设置、光栅化、剔除等一系列固定管线的几何操作
【ROP】“码头工人”,负责对片元着色器处理后的像素进行测试(像素的深度/模板测试和写入、颜色混合、抗锯齿)
【L2 Cache、Memory Controller和DRAM】
DRAM,“仓库”,最终像素数据会被放到DRAM中的帧缓存
Memory Controller,“码头”,处理从ROP过来的数据
L2 Cache,“码头临时仓库”
一个(ROP + Memory Controller + L2 Cache + DRAM)成为一个组合,共有6个组合,每个对应显存1/6物理地址。

【【TPC/GPC架构】芯片】
【Geometry Controller】
“快递驿站”- 顶点数据传输
职责:
1.顶点属性在芯片内的而输入输出;
2.几何着色器增删顶点改变拓扑结构;
3.把运算结构送到Viewport/clip/setup/raster/zcull block模块去进行光栅化。

【SM controller/SMC】
“子工厂高管”- 分配工作(负载平衡) + 获取资源
职责:
1.将各种任务拆分成Warp(一个Warp对应一组指令,伴随着32个线程),并分配给SM处理;
2.让SM可以获得共同部门Texture unit中的纹理资源(显存中的非纹理资源则通过ROP)。

【Texture unit】
“共享纹理仓库”
职责:
1.获取和过滤纹理;
2.含有Tex L1 cache,避免频繁读取。

【Streaming Multiprocessor/SM】
“一个部门”
处理从SMC分配过来的指令。
I cache(指令cache):缓存SMC分配下来的指令。
C cache(常量cache)与Shared Memory(共享内存)。
MT Issue:“部门主管”,将一组指令分成一条条指令塞给“工人”执行。
SP:“工人”,能处理浮点型标量运算、整型运算,如add、multiply、multiply-add。
SFU:“高级工人”,能处理复制运算,如超越函数、属性插值、透视校正。

指令生成pipeline:高级语言(着色器代码/CUDA Kernel)-> 中间指令 -> 二进制GPU指令
指令分类:
1.运算:浮点整数等加法乘法、最小最大、比较、类型转换等基础运算以及超越函数等复杂运算;
2.流控制:分支、调用、返回、中断、同步;
3.内存访问:包括对各类内存的读写、原子操作。

【SM内部pipeline】高性能并行的2个要素
1.SMC会拿到一组着色器所有的指令(伴随着32个线程,叫做一个Warp),塞给SM。指令存在SM的I cache里,MT Issue每次从缓存中拿出一条指令发送给SP和SFU们(每次发送1条指令,SP和SFU就并行执行32次,这就是SIMT,当然某些情况也会锁步,比如分支不同步的情况有的顶点进行A计算有的顶点进行B计算)。
2.由于内存的访问速度慢于计算速度,当SP遇到内存访问指令时,会从SMC向外界请求数据,造成等待时间。为了不浪费中间的等待时间,GPU做了“延迟隐藏”机制,即SMC会把多组Warp丢给SM,先把各类指令存在I cache里,出现内存阻塞时快速切换到其他另一批Warp上。

GPU最小执行单元
硬件:SM
软件:Warp,一般包含32个线程
一个Warp到底包含多少个线程合适?如果包含过多的线程,当出现访问内存“卡壳”时,太多的线程都在这个Warp中,不利于执行“延迟隐藏”;如果包含过少,切换成本就显得过高。

CUDA架构(软件层封装) - Grid-Block-Thread
一个Grid包含N个block,灵活指定
一个Block包含M个Thread,核函数写死,一般是32的倍数,因为最终也是分到Warp中处理

基于Warp的优化原则:
1.最好为每个Block分配Warp线程数(32)的整数倍线程数;
2.同一分支的线程要尽可能挤到同一Warp里;
3.如果不同线程需要从内存中读写相同的数据源,那么这些线程尽量都在一个Warp中,否则不同Warp需要为了保证数据同步而等待。

【【内存】】

【Global Memory与L2 cache】
(软件上供所有Grid共用)位于芯片外,每块DRAM与一个L2 cache相连,L2 cache可以供所有SM共同使用。
【Shared Memory与L1 cache】
位于SM中,读写速度远高于主存与L2 cache
L1 cache:Tesla架构的L1 cache只用于缓存纹理数据
(软件上供一个Block上的所有Thread共用)Shared Memory:一个warp32线程可能需要同时对共享内存进行读写。
【Local Memory与Register Files】
(软件上供一个线程独用)每一个寄存器中的内存,如果存不下会逐层溢出到 -> L1 cache -> L2 cache。