c – Strange / fp浮点模型标志行为
我正在检查一些使用/ fp:precise和/ fp:fast标志的代码.
根据MSDN documentation for / fp:精确:
查看对sqrtf的调用的反汇编(使用/ arch:SSE2,目标x86 / Win32平台调用): 0033185D cvtss2sd xmm0,xmm1 00331861 call __libm_sse2_sqrt_precise (0333370h) 00331866 cvtsd2ss xmm0,xmm0 从this question开始,我相信现代的x86 / x64处理器不使用80位寄存器(或至少不鼓励使用它们),因此编译器会做我认为是下一个最好的事情,并使用64位双精度进行计算.因为内在函数被禁用,所以调用了一个库sqrtf函数. 好吧,相当公平,这似乎符合文档所说的内容. 但是,当我为x64 arch编译时,会发生一些奇怪的事情: 000000013F2B199E movups xmm0,xmm1 000000013F2B19A1 sqrtps xmm1,xmm1 000000013F2B19A4 movups xmmword ptr [rcx+rax],xmm1 不使用64位双精度执行计算,并且正在使用内在函数.据我所知,结果与使用/ fp:fast标志的结果完全相同. 为什么两者之间存在差异? / fp:精确到不能与x64平台一起使用吗? 现在,作为一个完整性检查我在VS2010 x86中用/ fp:precise和/ arch:SSE2测试了相同的代码.令人惊讶的是,sqrtpd内在被使用了! 00AF14C7 cvtps2pd xmm0,xmm0 00AF14CA sqrtsd xmm0,xmm0 00AF14CE cvtpd2ps xmm0,xmm0 这里发生了什么?为什么VS2010在VS2012调用系统库时会使用内在函数? 针对x64平台的VS2010测试结果与VS2012相似(/ fp:精确度似乎被忽略). 我无法访问任何旧版本的VS,因此我无法在这些平台上进行任何测试. 作为参考,我正在使用Intel i5-m430处理器在Windows 7 64位中进行测试. 解决方法
首先,您应该阅读
this关于中间浮点精度的非常好的博文.这篇文章只处理visual studio生成的代码(但这就是你的问题所在).现在举例来说:
0033185D cvtss2sd xmm0,xmm0 此汇编代码已使用/ fp:precise / arch:SSE2为x86平台生成.根据documentation,精确的浮点模型促使x86平台上的所有计算内部加倍.它还可以防止使用内在函数(我认为你已经阅读了this information).因此,代码以从float到double的转换开始,然后是双精度sqrt调用,最后将结果转换回float. 000000013F2B199E movups xmm0,xmm1 第二个例子是为x64(amd64)平台编译的,这个平台的行为完全不同!根据文件:
因此,计算将在内部以单精度完成.我认为他们也决定尽可能使用内在函数,因此/ fp:precise和/ fp:fast之间的差异在x64平台上有点小.新的行为导致更快的代码,它使程序员能够更好地控制究竟发生了什么(他们能够改变游戏规则,因为兼容性问题与新的x64平台无关).遗憾的是,文档中未明确说明这些更改/差异. 00AF14C7 cvtps2pd xmm0,xmm0 最后,最后一个示例是使用Visual Studio 2010编译器编译的,我认为他们不应该使用sqrt的内在函数时最好不要(至少对于/ fp:精确模式),但他们决定更改/修复此行为再次在Visual Studio 2012中(参见here). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |