我问这个问题是因为我试图在Visual Studio 2017(cl.exe)和gcc 5.4.0之间实现按位(哈希)相等。有问题的函数使用sin()和cos()。所有变量都是双倍的,FMAD也是相关的。
我一直在关于浮点确定性,再现性和锁定MP游戏设计的SO和网络上广泛阅读。我知道单编译器,单构建确定性并不难,但我正在尝试2编译器,单构建确定性。
效率不是一个问题。我只想让结果匹配。
我问,因为我希望能够缩小我对测试/尝试的关注范围。
这些是否与x86_64处理器和构建相关?
我问,因为我已经读过SSE(x86_64)的平台默认使用SSE作为浮点,所以fpu控制函数应该无关紧要?
我发现this和this最具信息性。这个MSDN article表示在x64 arch上不支持设置浮点精度模板。 this SO post表示SSE具有固定的精确度。
我的测试表明/ fp:{strict,precise,fast}并没有改变哈希。优化级别也不是。因此,我希望将我的注意力集中在罪恶上,cos。
答案 0 :(得分:0)
大多数浮点函数必须以某种方式执行舍入。 C / C ++标准在这个主题上相当模糊,并且IEEE一致性对三角函数不够严格。这意味着在实践中尝试以便携方式挤出编译器默认数学实现的正确舍入是没用的。
例如,sin / cos的libm实现(由gcc使用)是用汇编语言编写的,并且算法对于不同的体系结构是不同的,并且很可能取决于库的版本。 / p>
因此,您有两种可能性:
在处理舍入错误时,我个人使用MPFR库作为黄金标准。虽然我从未试图将其与libm性能进行基准测试,但会有运行时成本。
自定义实施
请注意,如果您决定自己实现它,则需要选择舍入模式并通知编译器这对您来说很重要。
在C ++中,它是这样完成的:
#include <cfenv>
#pragma STDC FENV_ACCESS ON
#pragma STDC FP_CONTRACT OFF
int main(int, char**) {
...
if(!std::fesetround(FE_TONEAREST))
throw std::runtime_error("fesetround failed!");
...
}