所以我的问题是,为什么调用Vector2.Normalize(v)的结果在调用34次后从<0.9750545,-0.22196561>变为<0.97505456,-0.22196563>?
所以首先-为什么会发生变化。可以观察到更改,因为计算这些值的代码也会更改。
如果我们在代码的第一个执行过程中尽早进入WinDbg并稍微深入到计算Normalize
ed向量的代码中,我们将看到以下程序集(或多或少-我削减了一些部分):
movss xmm0,dword ptr [rax]
movss xmm1,dword ptr [rax+4]
lea rax,[rsp+40h]
movss xmm2,dword ptr [rax]
movss xmm3,dword ptr [rax+4]
mulss xmm0,xmm2
mulss xmm1,xmm3
addss xmm0,xmm1
sqrtss xmm0,xmm0
lea rax,[rsp+40h]
movss xmm1,dword ptr [rax]
movss xmm2,dword ptr [rax+4]
xorps xmm3,xmm3
movss dword ptr [rsp+28h],xmm3
movss dword ptr [rsp+2Ch],xmm3
divss xmm1,xmm0
movss dword ptr [rsp+28h],xmm1
divss xmm2,xmm0
movss dword ptr [rsp+2Ch],xmm2
mov rax,qword ptr [rsp+28h]
在执行大约30次之后(稍后会更多有关此数字),这将是以下代码:
vmovsd xmm0,qword ptr [rsp+70h]
vmovsd qword ptr [rsp+48h],xmm0
vmovsd xmm0,qword ptr [rsp+48h]
vmovsd xmm1,qword ptr [rsp+48h]
vdpps xmm0,xmm0,xmm1,0F1h
vsqrtss xmm0,xmm0,xmm0
vinsertps xmm0,xmm0,xmm0,0Eh
vshufps xmm0,xmm0,xmm0,50h
vmovsd qword ptr [rsp+40h],xmm0
vmovsd xmm0,qword ptr [rsp+48h]
vmovsd xmm1,qword ptr [rsp+40h]
vdivps xmm0,xmm0,xmm1
vpslldq xmm0,xmm0,8
vpsrldq xmm0,xmm0,8
vmovq rcx,xmm0
不同的操作码,不同的扩展名-SSE与AVX,我想,使用不同的操作码,我们将获得不同的计算精度。
那么现在更多关于为什么?.NET Core(不确定版本-假定为3.0-但已在2.1中进行了测试)具有称为“分层JIT编译”的内容。它的作用是在开始时生成快速生成的代码,但可能不是最佳的。只有在稍后运行时检测到代码被充分利用时,它才会花费一些额外的时间来生成新的,更优化的代码。这是.NET Core中的新事物,因此可能不会更早观察到这种行为。
又为什么要打34个电话?这有点奇怪,因为我希望这大约在30次执行时发生,因为这是开始进行分层编译的阈值。可以在coreclr的源代码中看到常量。何时启动可能还会有一些其他可变性。
只是为了确认是这种情况,您可以通过发出set COMPlus_TieredCompilation=0
并再次检查执行来设置环境变量来禁用分层编译。奇怪的效果消失了。
C:\Users\lukas\source\repos\FloatMultiple\FloatMultiple\bin\Release\netcoreapp3.1
λ FloatMultiple.exe
0000: <0,9750545 -0,22196561>
0001: <0,9750545 -0,22196561>
0002: <0,9750545 -0,22196561>
...
0032: <0,9750545 -0,22196561>
0033: <0,9750545 -0,22196561>
0034: <0,9750545 -0,22196561>
0035: <0,97505456 -0,22196563>
0036: <0,97505456 -0,22196563>
^C
C:\Users\lukas\source\repos\FloatMultiple\FloatMultiple\bin\Release\netcoreapp3.1
λ set COMPlus_TieredCompilation=0
C:\Users\lukas\source\repos\FloatMultiple\FloatMultiple\bin\Release\netcoreapp3.1
λ FloatMultiple.exe
0000: <0,97505456 -0,22196563>
0001: <0,97505456 -0,22196563>
0002: <0,97505456 -0,22196563>
...
0032: <0,97505456 -0,22196563>
0033: <0,97505456 -0,22196563>
0034: <0,97505456 -0,22196563>
0035: <0,97505456 -0,22196563>
0036: <0,97505456 -0,22196563>
这是预期的,还是语言/运行时的错误?
已有关于此的错误报告- 问题1119