如何配置Conda工具链生成与macOS默认工具链一致的汇编代码
不同Clang工具链编译浮点代码的结果差异及解决方法
问题复现
在macOS 11.6.1/arm64环境下,以下C程序用不同工具链编译后运行结果存在差异:
#include "assert.h" #include "stdio.h" int main() { double y[2] = {-0.01,0.9}; double r; r = y[0]+0.03*y[1]; printf("r = %24.26e\n",r); assert(r == 0.017); }
- 使用Xcode默认Clang(13.0.0版本)编译运行,输出
r = 1.70000000000000012212453271e-02,断言通过; - 使用Conda 23.1.0提供的cxx-compiler(内含Clang 14.0.6)编译运行,输出
r = 1.69999999999999977517983751e-02,断言失败。
差异根源
汇编代码分析显示:
- Xcode默认工具链采用
fmul(浮点乘法)+fadd(浮点加法)的分步指令完成计算; - Conda工具链则使用
fmadd(融合乘加)指令,该指令将乘法和加法合并为一步执行,仅进行一次舍入操作,而分步运算会经历两次舍入,最终导致数值结果出现差异。
编译参数调整方案
要让Conda工具链生成与Xcode默认工具链一致的汇编代码,可添加以下任一编译参数:
1. 直接禁用融合乘加优化
添加编译参数:-ffp-contract=off
该参数会强制编译器关闭浮点收缩优化,禁止自动使用fmadd这类融合指令,改为生成分步的fmul和fadd指令。
2. 指定精确浮点运算模型
添加编译参数:-ffp-model=precise
该参数要求编译器遵循更严格的浮点运算语义,限制可能改变运算结果的优化行为,其中就包括禁用自动融合乘加,确保运算步骤与默认工具链对齐。
内容的提问来源于stack exchange,提问作者Stéphane Mottelet
相关产品推荐
相关产品推荐

