CUDA C开发周期和优化因素

       了解应用程序如何使用GPU对确定性能提升的因素是至关重要的。NVIDIA提供了许多功能强大且易于使用的工具,它们能使开发过程引人入胜又轻松愉悦。以下部分包含了CUDA的开发周期和CUDA的性能优化策略。

1.APOD开发周期

      APOD是由NVIDIA特别为CUDA开发定制的迭代开发过程。APOD有4个阶段,如图所示:

  • 评估(assessment)
  • 并行化(parallelization)
  • 优化(optimization)
  • 部署(deployment)

1.1 评估

      第一阶段的任务是评估应用程序,确定限制性能的瓶颈或具有高计算强度的临界区。在这里,需要评估用GPU配合CPU的可能性,发展策略以加速这些临界区。

       在这一阶段,数据并行循环结构包含很重要的计算,应该始终给予其较高的评估优先级。这种循环类型是GPU加速的理想化情况。为了帮助找出这些临界区,应该使用性能分析工具来发掘出应用程序的热点。有些代码可能已经被转化为使用主机的并行编程模型(如OpenMP或pthreads)。只要现有的并行部分能够充分并行化,那么它们也将为GPU加速提供很好的目标。

1.2 并行化

       一旦应用程序的瓶颈被确定,下一阶段就是将代码并行化。这里有几种加速主机代码的方式,包括以下几个方面:

  • 使用CUDA并行库
  • 采用并行化及向量化编译器
  • 手动开发CUDA内核使之并行化

       将应用程序并行化的最直接方法就是利用现有的GPU加速库。如果应用程序已经使用了其他的C数学库,如BLAS或FFTW,那么就可以很容易转换成使用CUDA库,如cuBLAS或cuFFT。另一种相对简单并行化主机代码的方法是利用并行化编译器。Open-ACC使用开放的、标准的编译指令,它是为加速器环境显式设计的。Open-ACC扩展提供了充分的控制以确保数据常驻于接近处理单元的位置,并提供了一系列的编译指令。这些使得GPU编程更加简单,可跨并行和多核处理器。

       如果应用程序所需的功能或性能超出了现有的并行库或并行编译器所能提供的范围,那么在这种情况下,对并行化使用CUDA C编写内核是必不可少的。通过使用CUDA C,可以最大限度地使用GPU的并行能力。

       根据原代码的情况,可能需要重构程序来展现固有并行以提升应用程序的性能。并行数据分解在这一阶段是不可避免的。大规模并行线程间的数据划分主要有两种不同的方法:块划分和循环划分。在块划分中,要处理的数据元素被分成块并分配到线程中,内核的性能与块的大小密切相关。在循环划分中,每个线程在跳跃之前一次处理一个元素,线程数量和元素数量相同。数据划分要考虑的问题与架构特征和要实现的算法性质相关。

1.3 优化

        当组织好代码且并行运行后,将进入下一阶段:优化实现以提升性能。大致来说,基CUDA的优化可以体现在以下两个层次上:

  • 网格级(grid-level)
  • 内核级(kernel-level)

       在网格级优化过程中,重点是整体GPU的利用率和效率。优化网格级性能的方法包括同时运行多个内核以及使用CUDA流和事件重叠带有数据的内核执行。

       限制内核性能的主要原因有3个:

  • 内存带宽
  • 计算资源
  • 指令和内存延迟

        在内核级优化过程中,要关注GPU的内存带宽和计算资源的高效使用,并减少或隐藏指令和内存延迟。

        CUDA提供了以下强大且有用的工具,从而可以在网格级和内核级确定影响性能的因素:

  • Nsight Eclipse Edition(nsight)
  • NVIDIA可视化性能分析工具(nvvp)
  • NVIDIA命令行性能分析工具(nvprof)

         这些性能分析工具在优化处理中是十分有效的,并为提升性能提供了最好的意见。

​​​​​​​1.4 部署

        只要确定了GPU加速应用程序的结果是正确的,那么就进入了APOD的最后阶段,即如何利用GPU组件部署系统。例如,部署CUDA应用程序时,要确保在目标机器没有支持CUDA的GPU的情况下,程序仍能正常运行。CUDA运行时提供了一些函数,用于检测支持CUDA的GPU并检查硬件和软件的配置。但是,应用程序必须手动调整以适应检测到的硬件资源。APOD是一个迭代过程,它的目的是将传统的应用程序转化为性能力良好且稳定的CUDA应用程序。那些包含许多GPU加速申请的应用程序,可能多次经过了APOD的流水线周期:确定优化因素、应用和测试优化、验证加速实现,并再次重复这个过程。

2. 优化因素

       一旦正确的CUDA程序已作为APOD并行化阶段的一部分实现,那么在优化阶段就能开始寻找优化因素了。如前文所述,优化可以应用在各个层面,从重叠数据传输和数据计算这个层面来看,所有的优化方法都在于底层的微调浮点运算。为了取得更好的性能,应该专注于程序的以下几个方面,按照重要性排列为:

  • 展现足够的并行性
  • 优化内存访问
  • 优化指令执行

2.1 展现足够的并行性

      为了展现足够的并行性,应该在GPU上安排并发任务,以使指令带宽和内存带宽都达到饱和。

有两种方法可以增强并行性:

  • 在一个SM中保证有更多活跃的并发线程束
  • 为每个线程/线程束分配更多独立的工作

当在一个SM中活跃线程束的数量为最佳时,必须检查SM的资源占用率的限制因素(如共享内存、寄存器以及计算周期),以找到达到最佳性能的平衡点。活跃线程束的数量代表了在SM中展示的并行性的数量。但是,高占用率不对应高性能。根据内核算法的性质,一旦达到了一定程度的占用率,那么再进一步增加占用率就不会提高性能了。但是仍有机会从其他方面来提高性能。

能从两个不同的层面调整并行性:

  • 内核级(kernel level)
  • 网格级(grid level)

        在内核级,CUDA采用划分方法分配计算资源:寄存器在线程间被划分,共享内存在线程块间被划分。因此,内核中的资源消耗可能会限制活跃线程束的数量。在网格级,CUDA使用由线程块组成的网格来组织线程的执行,通过指定如下内容,可以自由选择最佳的内核启动配置参数:

  • 每个线程块中线程的数量
  • 每个网格中线程块的数量

通过网格配置,能够控制线程块中安排线程的方式,以向SM展示足够的并行性,并在SM之间平衡任务。

2.2 优化内存访问

      许多算法都是受内存限制的。对于这些应用程序和其他的一些程序,内存访问延迟和内存访问模式对内核性能有显著的影响。因此,内存优化是提高性能需要关注的重要方面之一。内存访问优化的目标是最大限度地提高内存带宽的利用率,重点应放在以下两个方面:

  • 内存访问模式(最大限度地使用总线上的字节)
  • 充足的并发内存访问(隐藏内存延迟)

      来自每一个内核的内存请求(加载或存储)都是由单个线程束发出的。线程束中的每个线程都提供了一个内存地址,基于提供的内存地址,32个线程一起访问一个设备内存块。设备硬件将线程束提供的地址转换为内存事务。设备上的内存访问粒度为32字节。因此,在分析程序的数据传输时需要注意两个指标:程序需要的字节数和硬件传输的字节数。这两者之间的差值表示了浪费的内存带宽。

       对于全局内存来说,最好的访问模式是对齐和合并访问。对齐内存访问要求所需的设备内存的第一个地址是32字节的倍数。合并内存访问指的是,通过线程束中的32个线程来访问一个连续的内存块。

2.3 优化指令执行

       有以下几种方法可以优化内核执行,包括:

  • 通过保证有足够多的活跃线程束来隐藏延迟
  • 通过给线程分配更多独立的工作来隐藏延迟
  • 避免线程束内出现分化执行路径

       尽管CUDA内核是以标量方式表示的,就像它在单一CUDA核心上运行一样,但是代码总是在线程束单元中以SIMT(单指令多线程)方式来执行的。当对线程束发出一条指令时,每个线程用自己的数据执行相同的操作。

       可以通过修改内核执行配置来组织线程。线程块的大小会影响在SM上活跃线程束的数量。GPU通过异步处理运行中的工作来隐藏延迟(如全局加载和存储),以使得线程束进度、流水线、内存总线都处于饱和状态。我们可以调整内核执行配置获得更多的活跃线程束,或使每个线程做更多独立的工作,这些工作是可以以流水线方式执行和重叠执行。拥有不同计算能力的GPU设备有不同的硬件限制条件,因此,在不同的平台上网格/线程块启发式算法对于优化内核性能有非常重要的作用。

       因为线程束内的所有线程在每一步都执行相同的指令,如果由于数据依赖的条件分支造成线程束内有不同的控制流路径,那么线程运行可能会出现分化。当线程束内的线程发生分化时,线程束必须顺序执行每个分支路径,并禁用不在此执行路径上的线程。如果应用程序的运行时间大部分花在分化代码中,那么就会显著影响内核的性能。

       线程间的通信和同步是并行编程中非常重要的特性,但是它会对取得良好的性能造成障碍。CUDA提供了一些机制,可以在不同层次管理同步。通常,有两种方法来显式同步内核:

  • 在网格级进行同步
  • 在线程块内进行同步

       同步线程中有潜在的分化代码是很危险的,可能会导致未预料的错误。必须小心以确保所有线程都收敛于线程块内的显式障碍点。总之,同步增加了内核开销,并且在决定线程块中哪个线程束符合执行条件时,制约了CUDA调度器的灵活性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值