GPU Microarch学习笔记

warp
gpu的线程从thread grid 到threadblock,一个thread block在cuda core上执行时,会分成warp执行,warp的颗粒度是32个线程。比如一个thread block可能有1024个线程,那么就会分成32个warp执行。
上图的cta(cooperative thread arrays)即为thread block。
warp内的32个线程是以lock-step的方式锁步执行,也就是在没有遇到分支指令的情况下,如果执行,那么执行的都是相同的指令。通过这种方式32个线程可以共享pc,源寄存器id和目标寄存器id。
虽然warp是以32的颗粒度,但是具体在gpu内部执行时,也可能是以16的颗粒度,分两次执行,比如早期的fermi架构。
如上图所示,两个warp scheduler,每个warp每次只能在16个cuda core上执行。
后续的pascal gpu架构 cuda core增加到了32个,每个周期都能执行一个warp。
寄存器
gpu的寄存器数量是影响划分cuda thread block的数量的原因之一,如下图所示[1]。
虽然内部执行是按照warp执行的,按照调度顺序和ready进行调度。但是寄存器的分配是静态的按照thread number分配的,而不是warp。在warp执行时,32个线程,每个线程读取源寄存器,写入目标寄存器。假设每个寄存器4b,那么每次32个线程读取128b。
因而128b也就是gpu l1 cache cacheline的大小。不同于cpu,每一级的cache都要维护mosei的一致性,对于gpu的thread来说,私有memory不需要共享,因此对于local memory可以write back。而全局共享memory则可以write evict。
cpu的寄存器,在编译器编译时,会根据寄存器的live time进行优化,而且在cpu内部执行时,进行重命名,在有限的寄存器数量上尽量地解决依赖问题。
gpu只在编译时优化,尽量减少对memory的使用,在内部执行时,如果针对每个warp都增加一个寄存器重命名单元,设计复杂。因此gpu每个线程需要的寄存器就是它编译时需要的寄存器上限(寄存器上限也可以通过编译器控制)。这就导致了实际gpu内部执行时对寄存器使用数量的波动。如下图[2]所示,因此也有很多文章研究如何优化寄存器的使用。
在编译时,nvcc可以通过指定--maxrregcount指定寄存器的数量,但是过多的寄存器会因为固定的寄存器资源而导致thread数量变少,过少的寄存器也会导致需要频繁的访问memory,因此也需要折衷。
warp divergence
之前讨论warp时说如果32个线程,没有遇到分支,那么每个线程都执行同一条指令,但是如果存在分支呢?
gpu没有cpu的分支预测,使用active mask和predicate register来构建token stack来处理遇到分支时的问题。
gpgpu-sim按照下图[3]模拟的token stack,其中的
另一种可能的token stack则是按照如下的方式构建,结合了指令,predicateregister和token stack。
上图[4]中的(b)即为编译出的汇编指令,ssy 0xf0即为push stack,if else分支指令结束重聚的指令地址为0xf0。每个warp会有当前的active pc寄存器和active mask寄存器。我们假设一个warp内有8个thread,在ssy0xf0指令执行时,会将active mask 压栈,压栈的内容包括fig1中的entry type ssy,active mask和re-convergence pc,也就是0xf0(从ssy 0xf0指令可以获得).
在分支指令@po bra 0xb8执行时,会将div(divergence),activemask(0xf0,这个并非pc,而是active mask,当前warp的每个thread的predicateregister拼接而成,8bit 每个bit表示一个thread是否满足if条件)和 0xb8(if语句块内的第一条指令的地址)压栈。
然后gpu会默认执行else分支(因为if需要跳转,else直接顺序执行),执行else分支时,需要对active mask取反,只执行不满足if条件的那些thread。
else分支的最后一条汇编指令末尾会增加.s flag用于标志popstack,此时pop指令会将active mask出栈,更新到active mask寄存器和active pc中,然后执行if 分支,直到执行完毕if内的最后一条指令,对应地址0xe8,此时再次出栈。
将当前active pc更新为0xf0,activemask更新为0xff,此时if else分支执行完毕,回到重聚点,所有线程继续lock-step锁步执行。
这里只假设一个if else,但是实际上可能存在if else的嵌套,因此第一步ssy 0xf0,可以理解成上下文切换时的先保存当前的activemask 0xff和重聚点的指令地址0xf0。
上述的方案与gpgpu-sim中的架构类似,除了在指令中显式的增加了压栈出栈,gpgpu-sim处理每一个分支都需要压栈if else两条分支,占用两项,而方案2)中每次除了保存当前active mask外,只需压栈一项。


蓝牙AoA技术与市场分析在深圳南山区隆重举行
变压器保护原理介绍 什么叫变压器充电保护?变压器的保护有哪些?
华为数据中心能源将开启下一代智能数据中心
人工智能技术预测有可能成为现实吗
小米12T Pro将首发2亿像素主摄
GPU Microarch学习笔记
IoT模块对家电智能化有很大的影响
上海理工太赫兹技术创新研究院在太赫兹超灵敏生物传感器方面取得新进展
广立微发布业界领先的可测性设计自动化和良率诊断解决方案
俄罗斯:启动官方自动驾驶测试
恩智浦推出一款新型回声消除及降噪解决方案
通过RAPIDS加速单细胞DNA和RNA基因组分析
Linus Torvalds发布Linux 6.3首个预览版
岩土工程监测振弦采集仪与振弦传感器的兼容性问题
触发器及其应用_钟控双稳态触发器详解
动环监控系统的介绍,它的特点有哪些
你未知的物联网专用通信技术,三种授权频段下的低功耗广域网
环境监测复杂多元,中科曙光先进计算从容应对
小型气象站的功能特点是怎样的
应用于健身房之中的镜面显示器可为你定制健身计划