使用Intel编译器获得一致的浮点数值计算结果

intel_iclifort intel_iclifort 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区

使用Intel编译器获得一致的浮点数值计算结果


大多数十进制的浮点数, 用二进制表示时不是完全一致的; 与此同时, 大多数与浮点数值相关的计算结果, 存在着固有的不确定性.

通常, 编写浮点计算应用软件希望达到如下的目标:
- 准确性:
意味着该产品产生的计算结果,应当”接近”于实际计算的结果; 评判的标准是误差值, 有时候也采用最后几位(“units in the last place”, ulp)
- 可复制性:
意味着该产品始终产生一致的结果, 无论运行的先后, 采用不同的编译选项, 使用不同的编译器, 还是在不同的处理器或者操作系统平台
- 性能:
计算应用当然运行得越快越好

但是, 这些目标往往是互相矛盾的. 而良好的编程习惯和合理地使用编译器选项, 能够帮助你很好地取得平衡. 正确的编译器选项, 可以得到一致的, 近乎可重现的结果, 也能保证足够快的性能(当然不是最佳的).


浮点运算规则

Intel编译器实现了一整套Microsoft引入的浮点运算规则模型, 具体内容可参考 Microsoft* Visual C++* Floating-Point Optimization: http://msdn2.microsoft.com/en-us/library/aa289157(vs.71).aspx

这个编译器开关选项 (Windows中使用/fp:, Linux 或 Mac OS X 使用-fp-model, 下同) 可以让你自由地选择最合适的编译器规则, 基于如下的条件:
- 数值安全 (value safety)
- 浮点表达式赋值 (FP expression evaluation)
- 浮点精度溢出 (precise FP exceptions)
- 浮点计算合并(FP contractions)
- 访问浮点运算单元(FPU)

如下列出了使用/fp: (-fp-model) 时的全部可选参数:
precise 只允许数值安全的优化
source | double | extended 指定浮点表达式赋值时使用的精度
except 激活严格的浮点溢出模式
strict 激活访问FPU; 不允许浮点计算合并, 比如乘加(fused multiply-add, fma); 默认使用 ‘prcise’ 和 ‘except’
fast[=1] (缺省选项) 允许数值不安全的优化, 编译器自行决定表达式赋值的精度; 不允许访问FPU; 允许浮点计算合并
fast[=2] 允许一些额外的近似值计算

这个编译器开关取代了一系列在旧版本的Intel编译器中使用的选项, 例如/Op, /QIPF-fltacc, /flt-consistency (-mp, -IPF-fltacc, -flt-consistency).

其中, 当浮点运算结果需要满足符合ANSI / IEEE C++ 和 Fortran 语言标准时, 推荐使用如下的编译器选项组合:
/fp:precise /fp:source (Windows)
-fp-model precise -fp-model source (Linux, Mac OS X)


一个Fortran应用的例子

与不使用优化编译选项相比, 该应用程序优化编译后产生了不同的结果, 并且这种差异以一种特定的形式不断扩大. 产生问题的根源被定位在代码中如下形式的表达式:
A(I) + B + TOL
相对于TOL是一个非常小的正数, A(I) 和 B 的值比较大. 当编译器生成优化代码时, 愿意采用如下的赋值形式:
A(I) + (B + TOL)
这样的话, 常数表达式 (B+TOL) 进入循环 I 之前就可以只需要赋值一次. 可是原来代码的目的是为了保证表达式的结果为正, 当 A(I) 约等于 –B. 一旦 TOL 直接与 B 相加, 由于浮点精度限制, 它往往会被就会直接被取整, 因此也就无法发挥它使得表达式的结果保持正数的作用.

最简单的解决办法就是, 使用编译器开关 –fp-model precise 重新编译受影响的代码文件. 这样就能防止表达式重新组合, 而是按照代码书写时的次序进行赋值.

当然, 更直接的解决方案, 不会带来过多的性能下降, 就是改写原始的代码为:
(A(I) + B) + TOL
这样就可以清楚地表达出编程者的意图, 同时别忘了编译时使用选项 –assume protect_parents


另一个WRF的例子 (Weather Research and Forecasting model)

我们观察到同一个应用运行在不同数量的处理器下的MPI(Messenge Passing Interface)环境中, 结果会出现细微的不同. 这是因为随着不同数量的MPI进程, 原始问题的分解方式会发生变化, 进而导致循环边界和数据对齐也相应变化. 结果导致循环向量化代码中的循环次数, 以及前后的处理代码都发生了变化, 最终导致同样的数据, 却产生了略微不同的计算结果.

解决的方法就是编译时使用 –fp-model precise. 这样会让编译器生成前后一致的代码和数学库调用, 无论在循环体中和循环前后.

有时候(并不是一定), 这样做会阻止循环被向量优化, 特别是由于可能会改变计算的顺序导致结果发生结果不同, /fp:precise (-fp-model precise) 选项禁止归约(reduction)计算的向量化或者自动并行化. 注意, OpenMP中的并行归约操作无法因此被自动禁止, 程序员应当知道它们是数值不安全的操作, 必须自行处理.


可能的性能影响

/fp:precise /fp:source (-fp-model precise –fp-model source) 禁止使用某些特定的优化, 因此会在一定程度上降低应用程序的执行速度. 不同类型的应用受到的影响可能会非常不同.

从SPECCPU2000fp 测试集的试验数据来看, 对原有 -O3 选项的性能影响比较大, 大约为15%-20%, 主要是其中许多高级别的循环优化往往需要重新排列操作顺序. 而对 –O2 的影响很小, 基本在 1% 左右.


额外注意事项

编译选项 /fp:precise /fp:source (-fp-model precise –fp-model source) 也应当在调试模式 /Od (-O0) 时使用. Intel 编译器11.1以前的版本中, /Od (-O0) 会默认使用 /Op (-mp), 因此即使在 Intel 64 架构中也同样会生成 x87 指令, 除非使用 /fp:source (-fp-model source).

从11.0编译器版本开始, 使用/fp:precise (-fp-model precise)后, 循环中包含数学函数例如: log(), sin(), 也不会自动被向量化. 因为它可能会导致一个函数调用不同的数学函数库, 从而返回与标准数学函数库不同的, 略有差别的结果. 编译器选项开关 /Qfast-transcendentals (-fast-transcendentals) 能够恢复原来 10.1 版本中的缺省行为, 重新激活向量化优化.


结束语

Intel编译器选项能够让你控制并在浮点数值计算的准确性, 可复制性和性能目标中自行取舍.

使用 /fp:precise /fp:source (Windows) 或者 –fp-model precise –fp-model source (Linux, Mac OS X) 能够显著提高浮点运算结果的准确性和可复制性, 同时降低对运算性能的影响.



进一步阅读信息

1) Dr. Martyn J. Corden, David Kreitzer: “Consistency of Floating-Point Results using the Intel? Compiler or Why doesn’t my application always give the same answer?” http://software.intel.com/en-us/articles/consistency-of-floating-point-results-using-the-intel-compiler/
2) Microsoft Visual C++* Floating-Point Optimization: http://msdn2.microsoft.com/en-us/library/aa289157(vs.71).aspx
3) The Intel? C++ and Fortran Compiler User and Reference Guides, “Floating Point Operations” section.
4) “Floating Point Calculations and the ANSI C, C++ and Fortran Standard” http://www.intel.com/cd/software/products/asmo-na/eng/330130.htm
or see the list at http://www.intel.com/cd/software/products/asmo-na/eng/330130.htm

...全文

相关推荐

高校及科研院所如何利用外部数据完善技术转移转化机制.docx

科易网基于40亿+科创知识图谱数据库,深度探索AI技术在技术转移、成果转化、技术经纪、知识产权、产业创新、科技招商等垂直领域的多样化应用场景,研究科技创新领域的AI+数智化解决方案,推动科技创新与产业创新智能化发展。

BIZKEEN

完全复现虚拟同步发电机VSG自适应惯量阻尼控制仿真、根轨迹、调节系数对比(Simulink仿真、Matlab代码实现)

内容概要:本文档围绕“【完全复现】虚拟同步发电机VSG自适应惯量阻尼控制仿真、根轨迹、调节系数对比”这一主题,利用Simulink和Matlab平台,系统性地实现了虚拟同步发电机(VSG)的自适应惯量与阻尼控制策略的建模与仿真。内容涵盖VSG的核心控制原理、系统动态响应特性分析、根轨迹绘制以及在不同调节系数下的性能对比研究,旨在深入剖析关键控制参数对系统稳定性与动态性能的影响机制,为新能源并网系统中提升频率支撑能力和暂态稳定性的控制策略设计提供理论依据和技术支持。; 适合人群:具备扎实的电力系统分析与自动控制理论基础,熟练掌握Matlab/Simulink仿真工具,主要从事新能源发电、微电网运行、电力电子变换器控制或电力系统稳定研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①开展虚拟同步发电机(VSG)的建模与先进控制策略的深入研究;②探究自适应惯量与阻尼控制对改善电网频率响应速度和平抑功率波动的作用机理;③运用根轨迹法进行系统稳定性分析,并指导控制器参数的优化整定;④完成高水平学术论文撰写或科研项目申报所需的仿真复现实验。; 阅读建议:本资源以“完全复现”为核心目标,提供了完整的仿真模型与配套代码。使用者应在深入理解同步发电机转子运动方程、虚拟惯量及阻尼物理意义的基础上,结合电力系统暂态稳定理论,逐步操作并调试仿真模型,尤其需关注不同调节系数变化对系统动态性能指标(如超调量、调节时间)的影响,从而深化对VSG内在控制机制与稳定边界的认知。

天天程序猿

员工满意度数据集(11列,12000 条记录)CSV 合成

详情介绍:该 HR 员工数据集含 12,000 条 ×11 列(满意度、绩效评估、项目数、月均工时、司龄、工伤、福利包、晋升、部门、薪资),无缺失值但无离职标签列,且存在数据质量问题(141 条负绩效评估、144 条负工时、49.4% 异常高工伤率、项目数仅 0/1/2),疑似经过修改或合成,不能直接做经典的员工离职预测,适合做满意度回归、薪资三分类、晋升预测或员工聚类分析,使用前必须清洗异常值并注意数据真实性限制。

神仙别闹

科技服务机构如何通过数据服务增强市场竞争力?.docx

科技服务机构如何通过数据服务增强市场竞争力?

BIZKEEN

基于双向DC-DC变换器的储能电池SOC充电+放电双模式Simulink仿真

内容概要:本文详细介绍了一种基于双向DC-DC变换器的储能电池SOC(荷电状态)充放电双模式Simulink仿真模型,旨在实现储能系统在充电与放电两种工作模式下的智能切换与精确控制。该模型依托Simulink平台搭建,通过检测电池SOC实时值,动态判断并切换充放电模式,有效防止过充与过放,提升电池使用寿命与能量利用效率。系统涵盖双向功率变换、电压电流双闭环控制、模式切换逻辑及保护机制等关键环节,充分体现了电力电子变换与电池管理系统(BMS)的深度融合。该仿真模型适用于微电网、电动汽车及可再生能源系统中的能量管理研究,为优化储能调度策略、提高系统稳定性提供了可靠的技术支撑。; 适合人群:具备一定电力电子技术、自动控制理论及Simulink建模基础,从事新能源、储能系统、电力系统仿真等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究储能电池在不同负载或发电条件下的充放电动态行为;②优化电池管理系统中SOC估算精度与充放电控制策略;③验证双向DC-DC变换器在能量双向流动中的响应特性与控制性能;④为微电网能量调度、电动汽车能量回收、风光储一体化系统等实际应用场景提供仿真验证与设计依据。; 阅读建议:建议结合Simulink仿真环境动手实践,深入理解主电路拓扑、控制环路设计及模式切换逻辑,同时可配合相关文献资料进一步探究PI控制、滞环控制等算法对系统动态性能的影响,以全面提升对储能系统能量管理机制的认知与设计能力。

荔枝科研社
评论 2
收藏 已收藏
分享
返回顶部