国展网站建设,做u盘的老外网站,中国电信备案网站,网站添加百度商桥WARP
GPU的线程从thread grid 到thread block#xff0c;一个thread block在CUDA Core上执行时#xff0c;会分成warp执行#xff0c;warp的颗粒度是32个线程。比如一个thread block可能有1024个线程#xff0c;分成32个warp执行。 上图的CTA#xff08;cooperative thre…WARP
GPU的线程从thread grid 到thread block一个thread block在CUDA Core上执行时会分成warp执行warp的颗粒度是32个线程。比如一个thread block可能有1024个线程分成32个warp执行。 上图的CTAcooperative 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的数量的原因之一。 虽然内部执行是按照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内部执行时对寄存器使用数量的波动。如下图所示因此也有很多文章研究如何优化寄存器的使用。 在编译时nvcc可以通过指定--maxrregcount指定寄存器的数量但是过多的寄存器会因为固定的寄存器资源而导致thread数量变少过少的寄存器也会导致需要频繁的访问memory因此也需要折衷。 WARP Divergence
之前讨论warp时说如果32个线程没有遇到分支那么每个线程都执行同一条指令但是如果存在分支呢
GPU没有CPU的分支预测使用active mask和predicate register来构建token stack来处理遇到分支时的问题。
GPGPU-sim按照下图模拟的token stack其中的 另一种可能的token stack则是按照如下的方式构建结合了指令predicate register和token stack。 上图中的b即为编译出的汇编指令SSY 0xF0即为push stackif else分支指令结束重聚的指令地址为0xF0。每个warp会有当前的active pc寄存器和active mask寄存器。我们假设一个warp内有8个thread在SSY 0xF0指令执行时会将active mask 压栈压栈的内容包括Fig1 中的entry type SSYactive mask和re-convergence pc也就是0xF0从SSY 0xF0指令可以获得.
在分支指令PO BRA 0xB8执行时会将DIV(divergence),active mask(0xF0这个并非pc而是active mask当前warp的每个thread的predicate register拼接而成8bit 每个bit表示一个thread是否满足if条件) 和 0xB8if语句块内的第一条指令的地址压栈。
然后gpu会默认执行else分支因为if需要跳转else直接顺序执行执行else分支时需要对active mask取反只执行不满足if条件的那些thread。
Else分支的最后一条汇编指令末尾会增加.S flag用于标志pop stack此时pop指令会将active mask出栈更新到active mask寄存器和active pc中然后执行if 分支直到执行完毕if内的最后一条指令对应地址0xE8此时再次出栈。
将当前active pc更新为0xF0active mask更新为0xFF此时if else分支执行完毕回到重聚点所有线程继续lock-step锁步执行。
这里只假设一个if else但是实际上可能存在if else的嵌套因此第一步SSY 0xF0可以理解成上下文切换时的先保存当前的active mask。
上述的方案与GPGPU-sim中的架构类似除了在指令中显式的增加了压栈出栈。
1. https://www.bu.edu/pasi/files/2011/07/Lecture2.pdf
2.Dynamic Warp Formation and Scheduling for Effificient GPU Control Flow
3. RegMutex: Inter-Warp GPU Register Time-Sharing
4. Analyzing Graphics Processor Unit (GPU) Instruction Set Architectures