更好的排版请阅读: https://we5lw6jk7r.feishu.cn/wiki/DhhbwZoczi3wubkmSiGcV7KLntd?from=from_copylink

并行编程模型的整理

基于编程接口的并行编程模型

标准编程接口

  • 受支持不同网络类型的 MPI 消息传递接口启发,当前有许多组织以及机构尝试为多种架构的计算设备提供统一的编程接口,从而实现程序在不同计算设备之间的性能可移植。

Cuda

  • nvidia 提供
  • 只能在 nvidia gpu 硬件上使用

OpenCL

  • Khronos 组织提出
  • 可以将各种处理器都抽象为统一的模型,包括 Intel 的 Xeon Phi、Nvidia GPU、AMD GPU、神威太湖之光 等硬件都可以使用
  • 缺点:编程接口很底层,程序开发效率低

SkelCL

  • 基于 OpenCL 优化,封装并简化了 OpenCL 的数据和任务管理操作

Bolt

  • 基于 OpenCL 优化,封装并简化了 OpenCL 的数据和任务管理操作
  • 实现了常用的并行算法

Boost.compute

  • 基于 OpenCL 优化,封装并简化了 OpenCL 的数据和任务管理操作
  • 实现了常用的并行算法

SYCL

  • Khronos 组织提出
  • OpenCL 之上的抽象层,SYCL 标准支持高维数组,简化了 OpenCL 中的数据与任务管理操作。

DPC++

  • Intel 提出
  • 基于 SYCL 设计的编程标准,对 SYCL 进行了扩展,支持跨 CPU 和协加速器的数据并行编程

C++ AMP

  • 微软提出
  • 比 OpenCL 拥有更高层次的计算设备抽象,因此代码非常简洁,只需要在 for 循环中指定计算域以及内嵌的 lambda 函数就能完成并行计算。C++ AMP 的支持多维数组以及内存数据布局(Row/column major, AOS, SOA),依托于 Visual Studio 的支持,以及微软为 C++ AMP 专门开发的并行算法库,其为 Windows 开发者提供了良好的支持。

(核心: 性能可移植) 适配不同编程接口的模板函数

  • 有一些编程模型通过用统一的接口适配不同的并行编程标准,达到使程序在不同架构计算设备之间性能可移植的目标。

Kokkos

  • 核心是(高维)数组的模版化抽象容器, 统一的接口适配不同的并行化后端,公开版本包括 OpenMP,Pthreads 和 CUDA
  • 帮助程序实现在不同架构的计算设备之间性能可移植的 C++ 模板,其核心是数组的抽象容器 view 以及数据并行操作的抽象类 functor。
  • view 不仅支持多维数组,还把内存对齐、下标映射、内存数据布局、以 及访问控制等封装起来。functor 类包含程序员定义的数据操作函数以及这些函数需要操 作的数组容器,其主要作用是将设备的执行空间与存储空间连接起来。
  • Kokkos 目前支持的 编程标准包括 OpenMP,Pthreads、CUDA、以及 OpenCL 等。

Raja

  • 帮助程序实现在不同架构计算设备间性能可移植的 C++ 模板库
  • 其参考了劳伦斯利物莫国家实验室的一系列结构以及非结构网格程序的特点,认为这些程 序中对网格进行遍历操作的 for 循环的各循环实例之间不存在数据依赖,可以并行执 行。RAJA 将这些 for 循环抽象成为模板函数,模板函数的参数包括用户指定的循环体执行 策略以及目标编程标准等。

(课题二)SEMD

OP2

  • OP2 将非结构网格程序划分为 4 部分:集合(边的集合,网格的集合等)、集合相关 的数据、集合之间的映射关系(边与网格的对应关系)、以及对集合的操作。
  • 其认为所有 非结构网格程序都是对相关集合进行算数操作,体现在代码上就是使用 for 循环对集合的 元素进行遍历,直接或通过映射关系间接访问并操作集合的数据。
  • 使用 OP2 可以实现程序 的节点间以及节点内并行,

    • 节点间并行基于 MPI 编程标准实现:在实现节点间并行 时,OP2 框架使用 ParMETISs[34]以及 PTScotch[35]对整个计算域的网格进行划分以确保节 点之间的负载平衡
    • 节点内并行根据后端 计算设备可以基于 Pthread、OpenMP、CUDA、OpenCL 等编程标准实现: 在实现节点内并行时,OP2 采用图着色算法实现节点内处理单元的任 务分配及负载平衡
  • 数据布局:OP2 框架还可以根据不同后端计算设备的特点,选择不同的数据布局 方式(AOS 或 SOA)。
  • 编译:早期的 OP2 框架基于 ROSE 源码编译器实现源码编译,而最新的 OP2 框架 [36]采用 LLVM-Clang 重新实现了源码编译功能。

基于编译指导语句的编程模型

基于编译指导语句的编程模型

  • 对于数量庞大的遗产代码,使用插入编译指导语句的方式可以帮助开发人员使用不同 计算设备对其进行加速。

OpenACC

  • OpenACC[16]是由 Cray、PGI、以及英伟达发起的一个编程标准, 与 OpenMP 类似,其允许将编译指导语句插入 Fortran,C 和 C++ 程序的代码中,以帮助编译器 将计算任务调度到协加速器上。
  • 目前对 OpenACC 进行支持的设备包括 NVIDIA GPU, AMD GPU, SW26010, Intel Xeon Phi,FPGA 等。OpenACC 的出现极大的方便了程序开发人员使用 协处理器加速数量庞大的遗产代码。

OpenHMPP

  • HMPP[18]是由 CAPS 组织发起的一种 基于编译指导语句的编程标准,其支持 C 和 Fortran 两种语言。目前 NIVIDA 系列 GPU 对 HMPP 进行了支持。
  • HMPP 编译器可以根据#pragma 编译指导语句生成在相应计算设备上执行的二 进制文件。

OpenMP 4.X

  • 自从 OpenMP 4.X[17]开始,OpenMP 中也引入了用于协处理器加速的指导语句, 目前 NVIDIA GPU, AMD GPU, Intel Xeon Phi、以及 IBM Power 处理器都对 OpenMP 4.X 进行 了支持。

Mint

  • 使用简单的 5 条编译指导语句将科学计算中广泛存在的串行 Stencil 代码转换为 CUDA 代码。

基于语言的编程模型

  • 当前还有许多工作设计新的编程语言,这些编程语言对并行编程所需的常用操作进行 总结,从而简化并行程序的开发难度。过去的很长一段时间,程序中描述算法的逻辑被性 能优化策略掩盖。针对特定计算设备进行性能优化后的代码基本被固定,不再具有良好的 可维护性,代码在进行跨计算设备移植时需要大范围重写。因此,程序开发人员往往采用 保守的方案,把性能优化留到最后一步。为了提高代码的性能可移植性,有研究将算法描 述和代码生成解耦,使用简单的语法对算法进行描述,然后再针对具体的计算设备生成相 应的优化代码,这样在不同的计算设备间移植算法时只需要对算法的代码生成模块进行替 换。本节将分别介绍算法描述与优化策略混合以及解耦的编程语言。

算法实现与优化混合的编程语言

X10

  • X10[22]是 IBM 在美国 DARPA 的 HPCS(High Productivity Computing Systems)项目中 提出的一种编程语言,其基于 JAVA 进行扩展,使用异步划分地址空间模型(APGAS Model) 管理 CPU 以及 GPU,删除了 JAVA 中的并行控制部分,引入了新的并发控制库。X10 通过简单 扩展后使用自身的语义替代 CUDA 的相关语义,简化了 GPU 编程[38]。

算法实现与优化解耦的编程语言

  • 目前,在高性能计算的某些特殊领域,已经有某些专用语言可以将程序的算法描述和代码生成完全解耦。该类领域专用语言能够帮助程序开发人员对领域算法进行描述,并在 不关心底层细节的情况下,仅通过调用优化接口就完成算法优化以及代码生成。

深度学习领域: TVM

  • 目前深度学习领域的研究十分活跃,每天都有新的神经网络算子(层)被提出来,以 期望进一步提升模型的精确度。同时,由于越来越多的厂商开始设计制作神经网络芯片, 运行神经网络模型时会有越来越多的后端计算设备可供选择。由于既要支持层出不穷的神 经网络算子(层),又要保证新的神经网络算子(层)可以运行于不同的后端计算设备之 上,深度学习框架面临着极大的挑战,由此导致了众多深度学习编译器项目的出 现。
  • TVM[23]是一套完整的深度学习优化框架,其包括神经网络模型的图优化层以及算子 优化层。图优化层会执行算子合并等操作以对计算图进行优化;算子优化层会针对特定后 端计算设备,为计算图中的算子生成优化的代码。