AMD OpenCL大学课程(10)

GPU线程及调度

     本节主要讲述OpenCL中的Workgroup如何在硬件设备中被调度执行。同时也会讲一下同一个Workgroup中的workitem,如果它们执行的指令发生diverage(就是执行指令不一致)对性能的影响。学习OpenCL并行编程,不仅仅是对OpenCL Spec本身了解,更重要的是了解OpenCL硬件设备的特性,现阶段来说,主要是了解GPU的的架构特性,这样才能针对硬件特性优化算法。现在OpenCL的Spec是1.1,随着硬件的发展,相信OpenCL会支持更多的并行计算特性,基于OpenCL的并行计算才刚刚起步。

1、Workgroup到硬件线程

     在OpenCL中,Kernel函数被workgroup中的workitem(线程,我可能混用这两个概念)执行。在硬件层次,workgroup被映射到硬件的cu(compute unit)单元来执行具体计算,而cu一般由更多的SIMT(单指令,线程)pe(processing elements)组成。这些pe执行具体的workitem计算,它们执行同样的指令,但操作的数据不一样,用simd的方式完成最终的计算。

    由于硬件的限制,比如cu中pe数量的限制,实际上workgroup中线程并不是同时执行的,而是有一个调度单位,同一个workgroup中的线程,按照调度单位分组,然后一组一组调度硬件上去执行。这个调度单位在nv的硬件上称作warp,在AMD的硬件上称作wavefront,或者简称为wave。

  上图显示了workgroup中,线程被划分为不同wave的分组情况。wave中的线程同步执行相同的指令,但每个线程都有自己的register状态,可以执行不同的控制分支。比如一个控制语句

if(A)

{

… //分支A

}

else

{

  … //分支B

}

    假设wave中的64个线程中,奇数线程执行分支A,偶数线程执行分支B,由于wave中的线程必须执行相同的指令,所以这条控制语句被拆分为两次执行[编译阶段进行了分支预测],第一次分支A的奇数线程执行,偶数线程进行空操作,第二次偶数线程执行,奇数线程空操作。硬件系统有一个64位mask寄存器,第一次是它为01…0101,第二次会进行反转操作10…1010,根据mask寄存器的置位情况,来选择执行不同的线程。可见对于分支多的kernel函数,如果不同线程的执行发生diverage的情况太多,会影响程序的性能。

2、AMD wave调度

   AMD GPU的线程调度单位是wave,每个wave的大小是64。指令发射单元发射5路的VLIW指令,每个stream core(SC)执行一条VLIW指令,16个stream core在一个时钟周期执行16条VLIW指令。每个时钟周期,1/4wave被完成,整个wave完成需要四个连续的时钟周期。

    另外还有以下几点值得我们了解:

  • 发生RAW hazard情况下,整个wave必须stall 4个时钟周期,这时,如果其它的wave可以利用,ALU会执行其它的wave以便隐藏时延,8个时钟周期后,如果先前等待wave已经准备好了,ALU会继续执行这个wave。
  • 两个wave能够完全隐藏RAW时延。第一个wave执行时候,第二个wave在调度等待数据,第一个wave执行完时,第二个wave可以立即开始执行。

3、NV warp调度

     work group以32个线程为单位,分成不同warp,这些warp被SM调度执行。每次warp中一半的线程被发射执行,而且这些线程能够交错执行。可以用的warp数量依赖于每个block的资源情况。除了大小不一样外,wave和warp在硬件特性上很相似。

4、Occupancy开销

    在每个cu中,同时激活的wave数量是受限制的,这和每个线程使用register和local memory大小有关,因为对于每个cu,register和local memory总量是一定的。

    我们用术语Occupancy来衡量一个cu中active wave的数量。如果同时激活的wave越多,能更好的隐藏时延,在后面性能优化的章节中,我们还会更具体讨论Occupancy。

5、控制流和分支预测(prediction)

   前面我说了if else的分支执行情况,当一个wave中不同线程出现diverage的时候,会通过mask来控制线程的执行路径。这种预测(prediction)的方式基于下面的考虑:

  • 分支的代码都比较短
  • 这种prediction的方式比条件指令更高效。
  • 在编译阶段,编译器能够用predition替换switch或者if else。

  prediction 可以定义为:根据判断条件,条件码被设置为true或者false。


例如上面的代码就是可预测的,

Predicate = True for threads 0,2,4….

Predicate = False for threads 1,3,5….

下面在看一个控制流diverage的例子

  • 在case1中,所有奇数线程执行DoSomeWork2(),所有偶数线程执行DoSomeWorks,但是在每个wave中,if和else代码指令都要被发射。
  • 在case2中,第一个wave执行if,其它的wave执行else,这种情况下,每个wave中,if和else代码只被发射一个。

在prediction下,指令执行时间是if,else两个代码快执行时间之和。

6、Warp voting

   warp voting是一个warp内的线程之间隐式同步的机制。

    比如一个warp内线程同时写Local meory某个地址,在线程并发执行时候,warp voting机制可以保证它们的前后顺序正确。更详细的warp voting大家可以参考cuda的资料。>

  

    在OpenCL编程中,由于各种硬件设备不同,导致我们必须针对不同的硬件进行优化,这也是OpenCL编程的一个挑战,比如warp和wave数量的不同,使得我们在设计workgroup大小时候,必须针对自己的平台进行优化,如果选择32,对于AMD GPU,可能一个wave中32线程是空操作,而如果选择64,对nv GPU来说,可能会出现资源竞争的情况加剧,比如register以及local meomory的分配等等。这儿还不说混合CPU device的情况,OpenCL并行编程的道路还很漫长,期待新的OpenCL架构的出现。

时间: 2024-08-03 05:43:17

AMD OpenCL大学课程(10)的相关文章

AMD OpenCL大学课程(2)

1.OpenCL架构       OpenCL可以实现混合设备的并行计算,这些设备包括CPU,GPU,以及其它处理器,比如Cell处理器,DSP等.使用OpenCL编程,可以实现可移植的并行加速代码.[但由于各个OpenCL device不同的硬件性能,可能对于程序的优化还要考虑具体的硬件特性].    通常OpenCL架构包括四个部分: 平台模型(Platform Model) 执行模型(Execution Model) 内存模型(Memory Model) 编程模型(Programming

AMD OpenCL大学课程(6)

GPU架构 内容包括: 1.OpenCLspec和多核硬件的对应关系 AMD GPU架构 Nvdia GPU架构 Cell Broadband Engine 2.一些关于OpenCL的特殊主题 OpenCL编译系统 Installable client driver   首先我们可能有疑问,既然OpenCL具有平台无关性,我们为什么还要去研究不同厂商的特殊硬件设备呢? 了解程序中的循环和数据怎样映射到OpenCL Kernel中,便于我们提高代码质量,获得更高的性能. 了解AMD和Nvdia显卡

AMD OpenCL大学课程(12) 性能优化案例NBody

    本节主要介绍NBody算法的OpenCL性能优化. 1.NBody     NBody系统主要用来通过粒子之间的物理作用力来模拟星系系统.每个粒子表示一个星星,多个粒子之间的相互作用,就呈现出星系的效果.      上图为一个粒子模拟星系的图片:Source: THE GALAXY-CLUSTER-SUPERCLUSTER CONNECTION,http://www.casca.ca/ecass/issues/1997-DS/West/west-bil.html    由于每个粒子之间都

AMD OpenCL大学课程(5)

OpenCL内存模型     OpenCL的内存模型定义了各种各样内存类型,各种内存模型之间有层级关系.各种内存之间的数据传输必须是显式进行的,比如从host memory到device memory,从global memory到local memory等等.     WorkGroup被映射到硬件的CU上执行(在AMD 5xxx系列显卡上,CU就是simd,一个simd中有16个pe),OpenCL并不提供各个workgroup之间的一致性,如果我们需要在各个workgroup之间共享数据或

AMD OpenCL大学课程(7)

6.Nvdia GPU Femi架构 GTX480-Compute 2.0 capability: 有15个core或者说SM(Streaming Multiprocessors ). 每个SM,一般有32 cuda处理器. 共480个cuda处理器. 带ECC的global memory 每个SM内的线程按32个单位调度执行,称作warp.每个SM内有2个warp发射单元. 一个cuda核由一个ALU和一个FPU组成,FPU是浮点处理单元. SIMT和SIMD SIMT是指单指令.多线程. 硬

AMD OpenCL大学课程(11)

性能优化 1.线程映射    所谓线程映射是指某个线程访问哪一部分数据,其实就是线程id和访问数据之间的对应关系. 合适的线程映射可以充分利用硬件特性,从而提高程序的性能,反之,则会降低性能.    请参考Static Memory Access Pattern Analysis on a Massively Parallel GPU这篇paper,文中讲述线程如何在算法中充分利用线程映射.这是我在google中搜索到的下载地址:http://www.ece.neu.edu/~bjang/pat

AMD OpenCL大学课程(13) OpenCL扩展

1.OpenCL扩展      OpenCL扩展是指device支持某种特性,但这中特性并不是OpenCL标准的一部分.通过扩展,厂商可以给device增加一些新的功能,而不用考虑兼容性问题.现在各个厂商在OpenCL的实现中或多或少的使用了自己的扩展.      扩展的类型分为三种: Khronos OpenCL工作组批准的扩展,这种要经过一致性测试,可能会被增加到新版本的OpenCL规范中.这种扩展都以cl_khr作为扩展名. 外部扩展, 以cl_ext为扩展名.这种扩展是由2个或2个以上的

AMD OpenCL大学课程(4)

Kernel对象:     Kernel就是在程序代码中的一个函数,这个函数能在OpenCL设备上执行.一个Kernel对象就是kernel函数以及其相关的输入参数.   Kernel对象通过程序对象以及指定的函数名字创建.注意:函数必须是程序源代码中存在的函数. 运行时编译:     在运行时,编译程序和创建kernel对象是有时间开销的,但这样比较灵活,能够适应不同的OpenCL硬件平台.程序动态编译一般只需一次,而Kernel对象在创建后,可以反复调用.   创建Kernel后,运行Ker

AMD OpenCL大学课程(3)

OpenCL内存对象:       OpenCL内存对象就是一些OpenCL数据,这些数据一般在设备内存中,能够被拷入也能够被拷出.OpenCL内存对象包括buffer对象和image对象. buffer对象:连续的内存块----顺序存储,能够通过指针.行列式等直接访问. image对象:是2维或3维的内存对象,只能通过read_image() 或 write_image()来读取.image对象可以是可读或可写的,但不能同时既可读又可写.        该函数会在指定的context上创建一个