自从OpenACC标准正式制定之后,已成为并行运算开发人员眼光汇聚的焦点,因为OpenACC让开发人员不再拘泥于“纯CPU多核”、“纯CPU集群OpenMP并行”、“GPU/CPU混合并行”。。。。等等复杂且令人眼花缭乱的架构,只要维护“一套代码”就可以在不同平台环境上顺畅运行,甚至你的GPU/CPU混合混合环境可以是支持CUDA的nVidia GPU,也可以说是支持OpenCL的AMD/ATI GPU。开发人员只要使用支持OpenACC的编译器(compiler,如PGI Accelerator版本)给予不同的“目标平台参数”,即可实现不同平台的加速运行效果。

2011年9月,PGI受NVIDIA邀请出席在圣安东尼奥举办的地球物理勘探(SEG)年会,并在年会上介绍PGI加速器编程模型。那时我们已经看到了相当多对PGI加速器模型和下一代加速器感兴趣的人,这些人来自于石油和天然气工业。通常情况下,这一领域科学家们都是研究大规模且高度并行化的问题,这也正是我们可以利用加速器来工作的地方。

日前,The Portland Group公司又利用 PGI Accelerator Fortran 编译器,与国外非常知名的CIG公司,合作将SEISMIC_CPML地震正演软件移植到GPU平台,仅仅花费5小时改写代码时间便得到500%性能提升,令业界十分震惊。以下我们将逐步介绍其执行过程(代码细节省略)。

  • 任务背景介绍:

1. CIG(Computational Infrastructure for Geodynamics,地球动力学计算架构)是一个专注于提供地球动力学相关应用的开源社区, 支持从各种地幔和地核动力学的地球动力学研究,地壳和地震动力学,岩浆迁移和地震

2. SEISMIC_CPML是一套基于 Fortran 90 的开源软件,使用C -PML(Convolutional Perfectly Matched Layer )或ADE-PML(Auxiliary Perfectly Matched Layer)的有限元差分法,解决2D或3D各向同性(isotropic)或各向异性(anisotropic)的弹性,粘弹性或多孔弹性波方程

3. 作者:法国国家科学研究院(CNRS)的Dimitri Komatitsch 与Roland Martin

  • 任务目标:用PGI编译器对3D-CPML有限元差分代码进行改动,移植到GPU集群
  • 执行过程:

1. 评估(evaluation):

a. 加速改写最大的困难点,在于“必须基于现有代码去改动”

b. 该程序必须有“正确算法”作支撑。如果原代码不具备并行化,则加速效果不会明显。如果完全不并行,则需要先改动源代码

c. “加速器”像蚂蚁雄兵一样,每个地方加速一点、积累起来就可以效果明显

d. 在评估的Seismic_CPML的三维各向同性的代码,我们看到的最花时间的几个步骤中包含8个并行循环,可以进行加速处理

e. 根据“评估计算(点击)”得到 2.5~2.6之间,值得进行并行优化。(注:如果评估计算低于1则不值得做,如果高于4是最理想的!)

f. Seismic_CPML使用MPI来分解Z维的问题空间。这点让我们能够利用多GPU特性,当然也增加了额外数据移动的性能损耗。

g. 源代码中处理MPI的部分,我们可以使用OpenMP线程,但OpenMP编译器不能自动处理分散式内存的优化作业,反而会增加更多的编程工作和复杂性,因此放弃用 OpenMP方案。

2. 开始执行:将原始MPI/OpenMP代码在系统上执行,结果如下图:

改写 Step 1:加入 set up code

由于这个应用是MPI代码,每个处理器对应一个GPU,因此我们得先写段代码确认一些作业能正常运行。下面 setDevice() 先将处理器分派hostid并将所有hostid纳入处理。

此外,为了保持整套代码能适用不同环境,因此一开头我们加入 _ACCEL(宏)做识别,外部用 -ta 参数来启动或关闭(代码省略)。  

改写 step 2:加入计区算指令 ”!$acc region“

花几分钟在8个并行回圈里加入6个“!$acc region“,得到以下执行结果:

问题:速度更慢,是原本的三倍时间

方法:透过 PGI 提供的工具(如下)找寻原因

% pgfortran -Mmpi=mpich2 –fast -ta=nvidia -Minfo=accel seismic_CPML_3D_isotropic_MPI_ACC_1.F90 -o gpu1.out 

得到原因:只加了 !$acc region指令,每次计算都需要在 host 与 device 之间复制数据。由于重复的数据复制,导致非常严重的浪费。

 

改写 step 3:花60分钟加入数据管理指令”!$acc data region “,可以让前次计算数据保留在 device 的内存,提供下次计算,减少98%以上数据复制作业。得到以下计算结果。(立即改善)

改写 step 4:再花120分钟将数据传输的顺序进行优化,得到以下结果:

改写 step 5:再花120分钟将演算法进行优化,得到以下结果:

 总计:前后总过花费310分钟(5小时多10分钟),性能提高634%(6.34倍)。

以上结果是在”单机多GPU“环境得出的结果。

那是否能将改写过的代码,直接在集群上得到类型的结果?请看下面的执行结果!