我已经编译了一个可执行文件,我正在为它提供完全相同的数据,在一台机器上运行(非多线程)但是我得到的错误约为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页上讨论了矢量化(“问题:在同一处理器上的相同数据上重新运行相同二进制文件的不同结果”).
我的建议是决定你是否需要原始的咕噜声或结果的完全再现性,然后根据它选择模式.