hel*_*922 5 c floating-point sse visual-studio-2010 visual-studio-2012
我正在检查一些使用/fp:precise和/fp:fast标志的代码.
按照MSDN文档为/fp:precise:
使用/ fp:精确地在x86处理器上,编译器将对float类型的变量执行舍入,以便为赋值和强制转换以及将参数传递给函数时具有适当的精度.这种舍入保证了数据不会保留大于其类型容量的任何重要性.使用/ fp:precise编译的程序可以比没有/ fp:precise编译的程序更慢更大./ fp:exact禁用内在函数; 而是使用标准的运行时库例程.有关更多信息,请参阅/ Oi(生成内部函数).
查看对sqrtf(调用/arch:SSE2目标x86/Win32平台)的调用的反汇编:
0033185D cvtss2sd xmm0,xmm1
00331861 call __libm_sse2_sqrt_precise (0333370h)
00331866 cvtsd2ss xmm0,xmm0
Run Code Online (Sandbox Code Playgroud)
从这个问题我相信现代的x86/x64处理器不使用80位寄存器(或者至少不鼓励使用它们),所以编译器会做我认为是下一个最好的事情并用64位双精度计算.因为内在函数被禁用,所以调用了一个库sqrtf函数.
好吧,相当公平,这似乎符合文档所说的内容.
但是,当我为x64 arch编译时,会发生一些奇怪的事情:
000000013F2B199E movups xmm0,xmm1
000000013F2B19A1 sqrtps xmm1,xmm1
000000013F2B19A4 movups xmmword ptr [rcx+rax],xmm1
Run Code Online (Sandbox Code Playgroud)
不使用64位双精度执行计算,并且正在使用内在函数.据我所知,结果与/fp:fast使用标志的结果完全相同.
为什么两者之间存在差异?难道/fp:precise根本无法与x64平台工作?
现在,作为一个完整性检查,我用/fp:precise和测试了VS2010 x86中的相同代码/arch:SSE2.令人惊讶的是,sqrtpd内在被使用了!
00AF14C7 cvtps2pd xmm0,xmm0
00AF14CA sqrtsd xmm0,xmm0
00AF14CE cvtpd2ps xmm0,xmm0
Run Code Online (Sandbox Code Playgroud)
这里发生了什么?为什么VS2010在VS2012调用系统库时会使用内在函数?
针对x64平台的VS2010测试结果与VS2012相似(/fp:precise似乎被忽略).
我无法访问任何旧版本的VS,因此我无法在这些平台上进行任何测试.
作为参考,我正在使用Intel i5-m430处理器在Windows 7 64位中进行测试.
小智 3
首先,您应该阅读这篇关于中间浮点精度的非常好的博客文章。本文仅处理 Visual Studio 生成的代码(但这就是您的问题的全部内容)。现在来看例子:
0033185D cvtss2sd xmm0,xmm1
00331861 call __libm_sse2_sqrt_precise (0333370h)
00331866 cvtsd2ss xmm0,xmm0
Run Code Online (Sandbox Code Playgroud)
/fp:precise /arch:SSE2此汇编代码是针对 x86 平台生成的。根据文档,精确的浮点模型促使所有计算在 x86 平台上内部加倍。它还阻止使用内在函数(我想您已经阅读了此信息)。因此,代码首先从 float 到 double 的转换,然后是双精度 sqrt 调用,最后将结果转换回 float。
000000013F2B199E movups xmm0,xmm1
000000013F2B19A1 sqrtps xmm1,xmm1
000000013F2B19A4 movups xmmword ptr [rcx+rax],xmm1
Run Code Online (Sandbox Code Playgroud)
第二个示例是针对 x64 (amd64) 平台编译的,该平台的行为完全不同!根据文档:
出于性能原因,中间运算以任一操作数的最宽精度而不是可用的最宽精度进行计算。
因此,计算将在内部以单精度完成。我认为他们还决定尽可能使用内在函数,因此/fp:precise和之间的差异在 x64 平台上/fp:fast要小一些。新的行为会产生更快的代码,并使程序员能够更好地控制到底发生的事情(他们能够改变游戏规则,因为新的 x64 平台不关心兼容性问题)。不幸的是,这些更改/差异并未在文档中明确说明。
00AF14C7 cvtps2pd xmm0,xmm0
00AF14CA sqrtsd xmm0,xmm0
00AF14CE cvtpd2ps xmm0,xmm0
Run Code Online (Sandbox Code Playgroud)
最后,最后一个示例是使用 Visual Studio 2010 编译器编译的,我认为他们不小心使用了 sqrt 的内部函数,而他们最好不要使用内部函数(至少对于/fp:precise模式),但他们决定在 Visual Studio 2012 中更改/修复此行为再次(参见此处)。
| 归档时间: |
|
| 查看次数: |
1967 次 |
| 最近记录: |