论文部分内容阅读
随着应用程序对性能需求的日益增长,高性能GPU逐渐成为主流的计算设备。由于GPU程序的性能严重依赖于优化的程度,程序员必须为每个GPU程序进行大量手工程序优化,包括许多与算法相关的高层GPU程序优化,以便充分发挥GPU平台的计算能力。然而,GPU的编程和优化一直是一个难题。尽管一些编程模型通过语言扩展和自动优化编译器提高了编程和优化的效率,但它们缺乏对算法相关的高层GPU程序优化的支持,因此程序员构造高性能GPU程序的难度仍然较大。例如,基于高性能函数库的编程模型无法感知算法相关的高层程序特征,即使是针对特定领域的DSL也只关注少数简单的算法特征。因此,构造一个能够感知算法特征的高性能GPU编程模型具有重要意义。 本文的主要研究内容是一个面向GPU程序优化的高性能编程框架和一组算法相关的高层GPU程序优化技术。我们的编程框架结合了程序员的高层知识与编译器的自动优化能力。通过使用面向程序优化的程序制导,程序员可以描述输入程序的并行化方案以及与算法相关的高层程序信息。然后,源到源编译器对输入程序进行自动分析、变换和优化,最终生成高性能GPU程序。此外,我们的编程框架还针对三类算法特征提出了三种关键的高层GPU程序优化技术,分别是删除稀疏数组冗余计算的立即数优化、共享内存优化和资源敏感的任务调度优化。 本文的主要贡献包括: 针对GPU程序编程难、优化难的问题,提出了一个以GPU程序优化为中心的高性能编程框架,能够在减少程序员输入的条件下生成高性能GPU程序,降低了编程和优化的难度。与以往的编程模型不同,该编程框架围绕一组与算法相关的高层GPU程序优化方法展开,包括稀疏数组的立即数优化、共享内存优化和资源敏感的任务调度优化,分别为它们设计了一组优化制导,用于向编译器传递必要的高层程序信息。此外,该编程框架还为多种GPU程序优化方法设计了一个源到源编译器,在语法树层次支持高层(针对特定算法特征的)和低层(针对通用程序特征的)GPU程序优化模块,从计算、访存、延迟三方面对输入程序进行全面的优化。 针对深度学习中动态的、非结构化的稀疏数组引入冗余计算的问题,提出了一种在运行时删除冗余指令的立即数优化方法,从而提高了计算效率。该方法首先基于PTX和CUBIN两种中间表示,分别提出了适配动态、非结构化稀疏数组的算法。其中,以PTX作为中间表示的算法能够删除所有冗余的计算指令,性能最好,但运行时开销较大;相反,以CUBIN作为中间表示虽然不能优化冗余的计算,性能稍差,但运行时开销非常小。因此,为了在运行时选择最合适的优化算法,该方法还基于稀疏数组的动态特征设计了一个选择模型,通过动态评估每种优化算法的性能收益,为深度学习中的稀疏运算选择最快的算法。实验结果表明,与已有的方法相比,我们的方法可以更好的适应动态变化的、非结构化稀疏数组,能够取得更好的优化效果。当稀疏程度达到90%时,我们的方法比cudnn的性能提升了290%。 为解决共享内存优化参数空间复杂且难以选择的问题,提出了一个基于多面体模型求解共享内存优化参数的方法,提升了科学计算类程序的访存效率。我们利用多面体模型自动推导所有候选的数据分块方案,并对每种方案能够减少的显存访问量进行量化。在此基础上,我们构建每种数据分块方案的解空间,以最小化显存访问量为目标,自动求解最优的方案和共享内存优化参数。实验结果表明,我们的方法能够为不同GPU平台求解最优的共享内存优化参数,平均能够获得手写GPU程序90%的性能。 为了解决不规则程序的负载均衡问题,提出了GPU平台上资源敏感的动态任务调度的方法,从而达到均衡线程负载和促进资源共享的目的。在深入分析GPU平台上的线程调度和资源共享方式后,我们发现调度到同一个流处理器的线程将受到任务之间的资源共享的影响,如果线程执行的任务之间存在有益的资源共享,则程序的性能将得到提升。因此,我们提出了资源敏感的动态任务调度优化,依据资源共享关系将线程和任务分组,并设计了分层动态任务调度算法。实验结果表明,我们的方法能够有效的降低不规则程序执行的时间,相比静态调度达到2.1倍的性能加速。