微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 什么可能导致确定性过程产生浮点错误

已经阅读过这个 question,我有理由确定使用具有相同输入的浮点算术的给定进程(在相同的硬件上,使用相同的编译器编译)应该是确定性的.我正在研究一个不成立的案例,并试图确定可能导致这种情况的原因.

我已经编译了一个可执行文件,我正在为它提供完全相同的数据,在一台机器上运行(非多线程)但是我得到的错误约为3.814697265625e-06,经过仔细的谷歌搜索,我发现实际上等于1 / 4 ^ 9 = 1/2 ^ 18 = 1/262144.这非常接近32位浮点数的精度等级(根据维基百科大约7位数)

我怀疑它与已应用于代码的优化有关.我正在使用intel C编译器,并且已经将浮动点推测变为快速而不是安全或严格.这会使浮点过程不确定吗?是否存在可能导致此行为的其他优化措施?

编辑:根据pax的建议,我重新编译了浮点投机的代码转向安全,我现在得到稳定的结果.这让我可以澄清这个问题 – 浮点推测实际上做了什么以及如何在应用于完全相同的输入时,导致相同的二进制(即一次编译,多次运行)产生不同的结果?

@Ben我正在使用英特尔(R)C 11.0.061 [IA-32]进行编译,而我正在运行英特尔四核处理器.

解决方法

几乎在任何有快速模式和安全模式的情况下,你都会找到某种权衡.否则一切都将以快速安全模式运行:-).

并且,如果您使用相同的输入得到不同的结果,那么无论您认为它有多少,您的过程都不是确定性的(尽管有经验证据).

我会说你的解释是最有可能的.将其置于安全模式,看看非确定性是否消失.这肯定会告诉你.

至于是否还有其他优化,如果您使用相同的编译器/链接器和相同的选项编译相同的硬件,它应该生成相同的代码.除了快速模式之外,我看不到任何其他可能性(或者由于宇宙射线而在内存中发生位腐烂,但这种可能性很小).

更新后:

英特尔有一份文件here,解释了他们在安全模式下不允许做的一些事情,包括但不限于:

>重新关联:(a b)c – > a(b c).
>零折叠:x 0 – > x,x * 0 – > 0.
>倒数乘法:a / b – >一个*(1 / B).

虽然您声明这些操作是编译时定义的,但英特尔芯片非常聪明.他们可以重新排序指令,以便在多cpu设置中保持管道完整,因此,除非代码明确禁止此类行为,否则事情可能会在运行时(而不是编译时)发生变化,以使事情保持全速运行.

这个(简要地)在该链接文档的第15页上讨论了矢量化(“问题:在同一处理器上的相同数据上重新运行相同二进制文件的不同结果”).

我的建议是决定你是否需要原始的咕噜声或结果的完全再现性,然后根据它选择模式.

原文地址:https://www.jb51.cc/c/115596.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐