1. 背景

在使用arm与x86平台进行高性能计算时,可能会产生计算结果差异,产生精度问题。这可能是由于芯片架构差异、浮点数计算实现、编译器数学库优化等等。其中,某些编译选项会进行浮点运算优化以提升计算性能,通过将其禁用或采用精度友好的编译选项,可以提高计算精度。

Devkit精度分析工具的编译选项识别功能可以识别出可能导致精度问题的编译选项并给出提示,帮助开发人员解决精度问题。下面是它给出提示的场景。

1.1 适用场景
1.1.1 场景一

Intel在使用O2以上或Ofast优化等级的时候,编译器对浮点运算应用更多的性能优化。为了获取更高的浮点计算精度,需要加上-fp-model=precise来保证精度。毕昇和GNU编译器可以用-ffp-contract=off来获得更高的精度。

  • 修改建议: 毕昇(clang/clang++/flang)、gcc/gfortran增加编译选项:-ffp-contract=off Intel(icc/ifort/ifx)增加编译选项:-fp-model=precise
1.1.2 场景二

FTZ和DAZ对非规定浮点数转化为0的处理会带来精度上差异,因此不使能FTZ选项会带来更好的精度。Intel编译器中-ftz会在除了-O0的其他-O优化等级上默认打开,可以使用-no-ftz编译选项选择关闭;毕昇编译器在-ffast-math或-Ofast下使能FTZ,也可以通过-fflushz或-Mflushz(仅对flang有效)选项单独开启FTZ功能;gcc/gfortran只在-ffast-math下使能FTZ。

  • 修改建议: 毕昇(clang/clang++/flang)去掉-ffast-math或-fflushz或-Mflushz编译选项 Intel(icc/ifort/ifx)增加编译选项:-no-ftz,或者去掉-ftz编译选项 gcc/gfortran去掉-ffast-math编译选项

下面将展示通过Devkit的编译选项识别功能识别到可能导致精度问题的编译选项并修复的案例。

2. 案例

以使用LAMMPS进行计算产生的精度问题为例,LAMMPS是一套开源的分子动力学模拟程序包,官网:https://www.lammps.org/

为了比较结果,将在两台不同架构的服务器上分别计算一些算例 ,以下是服务器的信息:

鲲鹏服务器:架构:arm64,CPU:Kunpeng-920,操作系统:openEuler 22.03 LTS

x86服务器:架构:x86_64,CPU:Intel® Xeon® CPU E5-2690 v3 @ 2.60GHz,操作系统:CentOS Linux 7 (Core)

2.1 LAMMPS的环境搭建及安装

LAMMPS详细的安装及使用方法可以参考官网文档https://docs.lammps.org/,下面是简单的介绍。

2.1.1 下载LAMMPS及依赖

下载LAMMPS、FFTW、MPICH安装包:

LAMMPS下载地址:https://www.lammps.org/download.html

FFTW下载地址:http://www.fftw.org/download.html

MPICH下载地址:https://www.mpich.org/downloads/

将下载下来的压缩包解压。本文中,笔者使用的版本分别为:lammps-5Jun2019、fftw-3.3.8、mpich-4.3.0。

2.1.2 安装依赖软件

安装fftw:

cd /path/to/fftw-3.3.8  
./configure --prefix=/path/to/install --enable-float  
make  
make install

安装mpich:

cd /path/to/mpich-4.3.0  
./configure --prefix=/path/to/install --enable-float  
make  
make install
2.1.3 安装LAMMPS
cd /path/to/lammps-5Jun19/src

在编译前,可通过make package-status查看包状态,使用make yes-package安装所需要的模块。运行算例时若提示缺失,可按提示安装对应的模块后重新编译。

编译时可选择:

make mpi #编译并行计算的可执行程序lmp_mpi  
make serial #编译串行计算的可执行程序lmp_serial

编译后可使用make clean-all清理产物。

2.1.4 运行算例

将软件内置的一个算例deposit作为示范,进入目录lammps-5Jun19/examples/deposit,运行可执行程序:

串行:

/path/to/lmp_serial < in.deposit.atom

并行:

/path/to/mpirun -n 2 /path/to/lmp_mpi < in.deposit.atom

之后在终端或者目录下的log.lammps文件中可以查看计算过程和结果。

2.2 修复精度问题
2.2.1 算例deposit

运行src/example/deposit的算例时,鲲鹏服务器和x86服务器的结果有差异,如下所示:

(为节省篇幅,略去大部分打印过程,我们直接看最后一步的结果)

鲲鹏:

[wangjiachun@localhost deposit]$ /home/wangjiachun/lammps-5Jun19/src/lmp_serial < in.deposit.atom  
LAMMPS (5 Jun 2019)  
······  
Step Atoms Temp E_pair TotEng Press   
······  
    9900      449    1.1501006   -5.3225732   -4.9421947   -0.6732754   
   10000      450    1.0027842   -5.2994965   -4.9652351  -0.62353406   
Loop time of 6.66666 on 1 procs for 10000 steps with 450 atoms  
······

x86:

[wangjiachun@localhost deposit]$ /home/wangjiachun/lammps-5Jun19/src/lmp_serial < in.deposit.atom  
LAMMPS (5 Jun 2019)  
······  
Step Atoms Temp E_pair TotEng Press   
······  
    9900      449    1.0038671   -5.1540302   -4.8220162  -0.56356384   
   10000      450   0.95642062   -5.2046982   -4.8858913  -0.70500643   
Loop time of 10.1272 on 1 procs for 10000 steps with 450 atoms  
······

可见第10000步的结果已产生明显差异。为了定位误差来源,在鲲鹏服务器上运行精度分析工具。

目标文件和函数选择了pair_lj_cut.cpp中的compute(可选其它的,只要能运行工具就行),在src目录下运行以下命令:

time /home/wangjiachun/DevKit-CLI-25.0.0-Linux-Kunpeng/devkit advisor precision -instrument -c "make clean-all;make serial -j" -p $(pwd) -e $(pwd)/pair_lj_cut.cpp:compute

在终端和preccheck.log中可以看到Warning信息(log中为详细信息):

Found inappropriate option/function enabled '-ffp-contract=[on|fast]' in files: angle.cpp, angle_charmm.cpp, angle_cosine.cpp,.... Use -ffp-contract=off for better precision. For details, see preccheck.log with the path below.

由此,我们知道LAMMPS中存在一个精度问题:LAMMPS使用的编译器为g++,默认会开启编译选项-ffp-contract=fast。该选项用于控制浮点运算优化,当等号右边为on或fast时,可能导致精度问题。为了提高浮点计算精度,可将其设置为-ffp-contract=off。

为了修复此问题,找到文件src/MAKE/Makefile.serial(若编译时使用的不是make serial而是make mpi,同目录下有对应的Makefile.mpi文件),在其第10行的CCFLAGS后面添加选项-ffp-contract=off。重新编译后再次运行算例,结果如下:

鲲鹏,加了-ffp-contract=off

[wangjiachun@localhost deposit]$ /home/wangjiachun/lammps-5Jun19_ffp/src/lmp_serial < in.deposit.atom  
LAMMPS (5 Jun 2019)  
······  
Step Atoms Temp E_pair TotEng Press   
······  
    9900      449    1.0038671   -5.1540302   -4.8220162  -0.56356384   
   10000      450   0.95642062   -5.2046982   -4.8858913  -0.70500643   
Loop time of 6.8988 on 1 procs for 10000 steps with 450 atoms  
······

在可见的输出中,鲲鹏服务器的计算结果与x86的相同,可再与软件内deposit文件夹中给出的样例输出文件log.27Nov18.deposit.atom.g++.1对比,结果也是相同的。该算例的精度问题已解决。

下面再给出两个可通过同样方式消除误差的算例,算例位于example目录下的同名文件夹中。

2.2.2 算例friction

鲲鹏,原版lammps

[wangjiachun@localhost friction]$ /home/wangjiachun/lammps-5Jun19/src/lmp_serial < in.friction   
LAMMPS (5 Jun 2019)  
······  
Step Temp E_pair E_mol TotEng Press Volume   
······  
   18000   0.11418143   -3.0485595            0   -3.0014364  -0.24776847    2444.9333   
   19000   0.11028213   -3.0473558            0    -3.001842  -0.30249398    2444.9333   
   20000   0.11512925   -3.0504969            0   -3.0029827  -0.36022205    2444.9333   
Loop time of 7.26269 on 1 procs for 20000 steps with 1724 atoms

鲲鹏,加了-ffp-contract=off

[wangjiachun@localhost friction]$  /home/wangjiachun/lammps-5Jun19_ffp/src/lmp_serial < in.friction   
LAMMPS (5 Jun 2019)  
······  
Step Temp E_pair E_mol TotEng Press Volume   
······  
   18000   0.11159326   -3.0416392            0   -2.9955843  -0.22725121    2444.9333   
   19000   0.11530974   -3.0457005            0   -2.9981118  -0.36488457    2444.9333   
   20000    0.1131733   -3.0417814            0   -2.9950744  -0.27902539    2444.9333   
Loop time of 7.53781 on 1 procs for 20000 steps with 1724 atoms  
······

x86

[wangjiachun@localhost friction]$ /home/wangjiachun/lammps-5Jun19/src/lmp_serial < in.friction   
LAMMPS (5 Jun 2019)  
······  
Step Temp E_pair E_mol TotEng Press Volume   
······  
   18000   0.11159326   -3.0416392            0   -2.9955843  -0.22725121    2444.9333   
   19000   0.11530974   -3.0457005            0   -2.9981118  -0.36488457    2444.9333   
   20000    0.1131733   -3.0417814            0   -2.9950744  -0.27902539    2444.9333   
Loop time of 9.59815 on 1 procs for 20000 steps with 1724 atoms  
······
2.2.3 算例obstacle

鲲鹏,原版lammps

[wangjiachun@localhost obstacle]$ /home/wangjiachun/lammps-5Jun19/src/lmp_serial < in.obstacle   
LAMMPS (5 Jun 2019)  
······  
Step Temp E_pair E_mol TotEng Press Volume   
······   
   24000            1  -0.36563663            0   0.32096935   0.99829393    1456.1594   
   25000            1  -0.37625073            0   0.31035525    1.0448379    1460.3972   
Loop time of 1.8479 on 1 procs for 25000 steps with 769 atoms

鲲鹏,加了-ffp-contract=off

[wangjiachun@localhost obstacle]$  /home/wangjiachun/lammps-5Jun19_ffp/src/lmp_serial < in.obstacle   
LAMMPS (5 Jun 2019)  
······  
Step Temp E_pair E_mol TotEng Press Volume   
······  
   24000            1  -0.33410442            0   0.35250156   0.93960021    1463.5903   
   25000            1  -0.37437615            0   0.31222983    0.9644765    1464.9391   
Loop time of 1.86162 on 1 procs for 25000 steps with 769 atoms  
······

x86

[wangjiachun@localhost obstacle]$ /home/wangjiachun/lammps-5Jun19/src/lmp_serial < in.obstacle   
LAMMPS (5 Jun 2019)  
······  
Step Temp E_pair E_mol TotEng Press Volume   
······  
   24000            1  -0.33410442            0   0.35250156   0.93960021    1463.5903   
   25000            1  -0.37437615            0   0.31222983    0.9644765    1464.9391   
Loop time of 2.59319 on 1 procs for 25000 steps with 769 atoms  
······
Logo

鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。

更多推荐