Page 16 - 《软件学报》2025年第12期
P. 16

于恒彪 等: 面向编译优化结果不一致的代码高效定位                                                       5397


                 PLiner 使用的  CG  和  SP  应用)、开源  GNU scientific library (GSL) 中能够触发编译优化结果差异性的     10  个函数
                 和  floatsmith  混合精度测试集中能够触发编译优化结果差异性的              2  个程序, 共计  18 329  行代码. 其中  CG、MG、
                 SP  和  LU  来自  NPB  测试集, 分别为共轭梯度不规则存取和通信、多重网格长短距离通信、标量五对角线求解器
                 和下上高斯-赛德尔求解器. 需要特别指出的是              NPB  应用不同规模下的浮点计算行为和结果校验均不同. 函数                 sin、
                 sinc、cos、dilog、expint_E1、expint_E2、clausen、Ci、bessel_J1  和  bessel_y0  来自  GSL  数学库中  Specfunc 类函
                 数, 分别为正弦、辛格、余弦、二重对数、指数积分                  E1、指数积分    E2、克劳森、余弦积分、贝塞尔            J1  和贝塞
                 尔  y0  计算函数; arclength  和  dft 来自  floatsmith  测试集, 分别用于弧长计算和离散傅里叶变换计算. 实验选取的测
                 试用例均为多文件或多函数程序; PLiner 实验所使用的其他                 100  个简单合成用例都是数十行代码的单一函数,
                 FI3D  可直接定位这些简单用例, 考虑到         FI3D  是面向实际数值程序的编译优化结果差异性定位, 为了简洁性, 未在
                 实验中列出这些简单函数的定位情况.
                    实验基于    LLVM  编译器   (版本  17.0.1) 编译运行测试程序, 触发测试用例结果不一致性的基础编译优化选项
                 和激进编译优化选项分别为-O0          和-O3 -ffast-math. 因为-O0  是最基础的编译选项, 会关闭几乎全部编译优化策略,
                 能够最直接反映程序计算行为, 而-O3 -ffast-math       是开发人员最常用的激进编译优化选项, 会开启绝大部分浮点激
                 进编译优化    (例如-freciprocal-math  和-fassociative-math  等). -O0  和-O3 -ffast-math  便于触发编译优化结果不一致性
                 来评测   FI3D; PLiner 实验中也是选取了该组编译选项来进行实验.
                    NPB  程序和  GSL  函数结果不一致性的定义如下.
                    (1) NPB  程序: NPB  程序运行结束后会将计算结果与预存的标准结果进行校验, 如果相对误差不超过给定阈
                 值则输出   successful, 否则输出  fail. 因此, NPB  程序编译优化结果不一致性是指-O0       选项下编译运行程序结果校验
                 为  successful, 而-O3 -ffast-math  选项下编译运行结果校验为  fail; NPB  程序内部为不同规模定义了对应的输入和
                 标准计算结果. 为了更好地评估          FI3D  的有效性, 与  PLiner 类似, 本文调整了   NPB  程序的相对误差阈值, 使得-O0
                 和-O3 -ffast-math  两组选项能够产生结果不一致性. 误差阈值的设置是基于二分搜索获取的, 即在误差阈值范围区
                 间内不断二分搜索直到获取的误差阈值能够使得-O0                 返回  successful, 而-O3 -ffast-math  返回  fail.
                    (2) GSL  函数和  floatsmith  函数: 实验为这些函数定义了相对误差阈值, 函数的标准结果采用               long double 模式
                 和-O0  编译运行得出并在函数中预存, 当函数运行结果与标准结果的相对误差超过阈值则返回                               fail, 否则返回
                 successful. 误差阈值的设置策略与    NPB  类似.
                    本文实验的硬件运行环境为           12  代酷睿  i7  处理器, 拥有  16  个  CPU  核心, 主频  2.5 GHz. 软件环境为  Ubuntu
                 20.04.6  操作系统.
                  4.4   实验结果
                    (1) 研究问题   1: 有效性
                    表  3  给出了编译优化结果不一致性的定位结果, [func 1 :line 1 –line 2 ] 表示问题代码位于函数        func 1  中的  line 1 行
                 到  line 2 行. 第  2  列和第  3  列分别是  PLiner 和  FI3D  的定位结果. FI3D  能够有效定位所有程序触发结果不一致性的
                 代码段, 而  PLiner 则存在  4  个程序  (CG.A、MG.A、dilog  和  bessel_J1) 不能有效精确定位. 不难发现, PLiner 定位
                 失败的程序, 触发结果不一致性的问题代码分布在多个函数内, 这也反映了                     PLiner 的二分搜索定位存在的不足和        FI3D
                 的  Delta-Debugging  搜索的有效性. 对于  PLiner 定位成功的程序, FI3D   的定位结果与其一致, 这也反映出了           FI3D
                 实现的正确性. 实验发现浮点乘加优化、结合律优化和倒数优化等优化模式容易导致浮点程序结果的不一致性.
                    研究问题    1: FI3D  能够有效定位   NPB  应用、GSL  数学函数和     floatsmith  测试程序触发编译优化结果不一致
                 性的代码, 对于    PLiner 定位失效的   4  个包含多源问题代码的程序         CG.A、MG.A、dilog  和  bessel_J1, FI3D  能够进
                 行有效定位.
                    (2) 研究问题   2: 高效性
                    浮点指令差异性引导对搜索效率的提升主要来自两个方面原因: 通过过滤计算行为未被编译优化改变的文件/
                 函数来缩小问题代码搜索空间和通过将浮点计算行为改变程度大的文件/函数放置在待定位列表的前部来引导定
   11   12   13   14   15   16   17   18   19   20   21