加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – Strange / fp浮点模型标志行为

发布时间:2020-12-16 05:03:02 所属栏目:百科 来源:网络整理
导读:我正在检查一些使用/ fp:precise和/ fp:fast标志的代码. 根据MSDN documentation for / fp:精确: With /fp:precise on x86 processors,the compiler will perform rounding on variables of type float to the proper precision for assignments and cas
我正在检查一些使用/ fp:precise和/ fp:fast标志的代码.

根据MSDN documentation for / fp:精确:

With /fp:precise on x86 processors,the compiler will perform rounding on variables of type float to the proper precision for assignments and casts and when passing parameters to a function. This rounding guarantees that the data does not retain any significance greater than the capacity of its type. A program compiled with /fp:precise can be slower and larger than one compiled without /fp:precise. /fp:precise disables intrinsics; the standard run-time library routines are used instead. For more information,see /Oi (Generate Intrinsic Functions).

查看对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)平台编译的,这个平台的行为完全不同!根据文件:

For performance reasons,intermediate operations are computed at the widest precision of either operand instead of at the widest precision available.

因此,计算将在内部以单精度完成.我认为他们也决定尽可能使用内在函数,因此/ fp:precise和/ fp:fast之间的差异在x64平台上有点小.新的行为导致更快的代码,它使程序员能够更好地控制究竟发生了什么(他们能够改变游戏规则,因为兼容性问题与新的x64平台无关).遗憾的是,文档中未明确说明这些更改/差异.

00AF14C7  cvtps2pd    xmm0,xmm0

最后,最后一个示例是使用Visual Studio 2010编译器编译的,我认为他们不应该使用sqrt的内在函数时最好不要(至少对于/ fp:精确模式),但他们决定更改/修复此行为再次在Visual Studio 2012中(参见here).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读