Page 9 - 《软件学报》2025年第12期
P. 9
5390 软件学报 2025 年第 36 卷第 12 期
更高的浮点表达式替换重写; ACESE [10] 基于误差微结构和统计信息来获取浮点误差分布, 并通过程序综合生成多
项式补丁代码来修复精度问题. 在 FI3D 定位到导致编译优化结果不一致性的问题代码段后, 可以使用上述浮点精
度修复技术对这些代码段进行重写, 使得程序既可以获得高级别编译优化带来的性能提升又能够确保结果可复现
性. 需要特别指出的是高精度浮点执行在绝大部分情况下可以解决浮点舍入误差问题, 但是并不适用于那些罕见
的浮点特定精度 (precision-specific) [ 25 ] 运算场景. 例如, GLIBC 库的 exp 函数定义了双精度浮点变量
n=6755399441055744.0, 使用语句 (x+n)–n 来对双精度浮点数 x 取整, 显然该取整功能只面向双精度浮点数, 将变
量 x 和 n 提升为更高精度则会破坏程序原有语义.
2 背景知识
本节主要介绍浮点表示、编译优化结果差异性和基于精度增强的编译优化结果差异性定位.
2.1 浮点表示和编译优化结果差异性
浮点数是实数在计算机内部的近似表示. IEEE-754 [26] 是应用最广泛的浮点数编码标准, 一个浮点数可以表示
S
E
为: (–1) ×M×2 . 符号位 S 为 1 表示负数, 0 表示正数; M=m 0 .m 1 m 2 …m n 是尾数, 其中 m 0 为隐藏位, .m 1 m 2 …m n 是 n
p–1
位尾数位; E=e–bias 是 p 位阶码, 其中 e 是按位存储的偏置阶码, 偏置值 bias 为 2 –1. 表 1 给出了不同精度浮点
数 IEEE-754 的编码格式.
表 1 IEEE-754 浮点编码格式
精度 符号位 阶码 尾数
fp16 1 5 10
float 1 8 23
double 1 11 52
由于浮点数采用有限精度编码, 舍入误差不可避免. 当一个实数不能被浮点数精确编码表示时, 会根据系统的
舍入模式 (例如就近舍入) 对其进行近似表示. 假定 R 和 F 分别表示实数和浮点数集合, 给定实数 x (x∈R), 它的浮
点表示为 x f (x f ∈F), 对应的舍入误差为 x–x f . 绝对误差 (absolute error, Err abs ) 和相对误差 (relative error, Err rel )
被广泛用来衡量舍入误差. 给定浮点函数 f(x), 假定 f r (x) 表示函数的精确计算结果, 绝对误差 Err abs 和相对误差
Err rel 的定义如下:
Err abs ( f(x), f r (x)) = | f r (x)− f(x)| (1)
f r (x)− f(x)
Err rel ( f(x), f r (x)) = (2)
f r (x)
由于浮点舍入误差的存在, 浮点运算并不满足实数运算的相关优化理论, 因此编译器的激进优化会改变浮点
计算行为, 例如常用的-ffast-math 优化选项; Intel 科技报告 [1] 中专门介绍了 ICC 编译器各种编译优化选项可能导
致的结果差异性. 需要特别指出的是相同的编译选项在不同编译器中的优化含义有可能不同, 例如-O3 选项在
IBM XLC 编译器中会执行 IEEE-754 不安全的优化遍, 而在 GCC 编译器中则不会.
美国劳伦斯利弗莫尔国家实验室 (LLNL) 在使用 XLC 编译器和-O3 选项编译运行流体动力学应用 Laghos
(https://github.com/CEED/Laghos) 时产生了明显不一致的能量计算结果, 开发人员耗费了大量的精力来分析汇编
代码查找-O3 选项产生结果不一致性的原因. 图 1 给出了 Laghos 应用中提取的触发编译优化结果不一致性的核
心代码示例 [4] . 当使用 XLC 编译器基于-O2 选项编译运行该示例程序时输出−1.350 7, 而 XLC 编译器基于-O3 选
项编译运行则输出-inf. 通过检查代码生成的汇编代码发现第 6 行代码中的除法操作在-O3 选项下被优化为了求
倒数操作和乘法操作. 由于 gradv10 是一个非规格化浮点数, 2*gradv10 求倒数时发生了浮点上溢出异常. 实验室
开发人员分析后通过将代码中的浮点变量由 double 类型提升为 long double 类型在-O3 选项下编译运行也能够产
生与-O2 一致的能量计算结果.

