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

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



                                                            −    −
                                                                −
                                                                −
                                                               −



                                     图 1 Laghos 应用中提取的编译优化结果不一致性示例程序

                  2.2   PLiner 编译优化结果差异性定位
                    高效定位导致编译优化结果差异性的代码对于数值程序的结果可复现性和性能优化具有重要意义, 即开发人
                 员可以仅对定位到的代码片段进行基于精度提升或者表达式重写的浮点精度修复, 使得程序在进行高级别编译优
                                            [4]
                 化时仍具有结果的可复现性; PLiner 是现有最先进的编译优化结果差异性定位工具, 能够进行语句级问题代码定位.
                    图  2  给出了  PLiner 框架图; PLiner 的出发点是浮点表达式在提升为高精度后, 浮点舍入误差问题会极大缓解,
                 浮点运算行为接近相应的实数运算, 从而避免了激进编译优化对浮点计算行为的影响                               (忽略特殊的    precision-
                 specific 操作). 因此, PLiner 基于浮点表达式精度增强来不断搜索定位导致编译优化结果不一致性的代码.


                                   程序 P             分层二分搜索                       精度增强
                                                                      P located
                                                  函数/循环/基本块/语句
                                 选项 C 1 &C 2                                      变换
                                                                                  P enhanced

                                                               C 1  和 C 2  结果是否一致
                                                 不一致性                           编译&运行
                                                 定位报告

                                       图 2 PLiner 编译优化结果差异性问题代码定位框架图

                    PLiner 的输入包括待分析的程序        P、导致计算结果不一致的编译优化选项              C 1 和  C 2  (假定  C 2 为高级别编译优
                 化选项); PLiner 会对程序进行分层二分搜索定位. 首先, 在函数层面会将                P  中所有函数都定位为可疑代码          P located ;
                 然后, 调用  LLVM  优化遍   (optimization pass) 自动将可疑代码中的浮点操作提升为        long double 类型, 生成精度增
                 强后的程序    P enhanced . 为了便于扩展支持更多的编译器和硬件架构, PLiner 在源代码层面做语句精度提升变换; 接
                 着, 会采用激进编译优化选项         C 2 编译运行  P enhanced , 如果结果不一致性消失, 则表明问题代码段位于当前定位的可
                 疑代码   P locate 内, 会在后续搜索时将   P locate 中函数列表均分, 再重复该定位过程, 否则返回最近通过精度提升解
                                                  d
                           d
                 决结果不一致性的函数列表. 在定位到问题函数后, PLiner 会依次对问题函数内部的循环体、基本块、基本块内
                 的语句依次采用类似的基于精度提升的二分搜索进一步定位, 最终得到导致编译优化结果不一致的问题语句集.
                    PLiner 存在如下  3  个主要不足.
                    (1) 缺乏对多源问题代码的定位支持. 假设程序             P  包含  4  个函数<func 1 , func 2 , func 3 , func 4 >且问题代码位于函
                 数  func 2 和  func 3 中. 4  个函数都转换为高精度能够修正结果不一致性问题, 二分搜索会将函数列表均分, 而对均分
                 后的两个函数列表<func 1 , func 2 >和<func 3 , func 4 >分别提升精度均不能修正结果不一致性问题, 最终会导致           PLiner
                 返回全部   4  个函数的列表<func 1 , func 2 , func 3 , func 4 >, 不能有效精确定位导致结果不一致性的函数  func 2 和  func 3 .
                    (2) 搜索效率不高. 二分搜索效率依赖函数列表的排序布局, 由于缺乏每个函数浮点计算行为受激进编译优化
                 的影响程度信息, 默认的函数排序会导致问题函数定位效率低. 例如, 假设程序                       P  包含  4  个函数<func 1 , func 2 , func 3 ,
                 func 4 >且问题代码位于函数     func 4 内, 二分搜索过程中会尝试       5  次精度增强转换和编译执行才会定位到              func 4 .
                 {<func 1 >, √}表示提升  func 1 精度成功解决了结果不一致性问题, {<func 1 >, ×}表示提升     func 1 精度没有解决结果不
                 一致性问题; PLiner 对程序     P  的精度提升定位过程为 {<func 1 , func 2 , func 3 , func 4 >, √} → {<func 1 , func 2 >, ×} →
                 {<func 3 , func 4 >, √} → {<func 3 >, ×} → {<func 4 >, √}. 而如果列表顺序变为<func 4 , func 1 , func 2 , func 3 >, 二分搜索过程
   5   6   7   8   9   10   11   12   13   14   15