Jadi pertanyaan saya adalah, mengapa hasil pemanggilan Vector2.Normalisasi (v) berubah dari <0,9750545, -0,22196561> menjadi <0,97505456, -0,22196563> setelah memanggilnya 34 kali?
Jadi pertama - mengapa perubahan terjadi. Perubahan diamati karena kode yang menghitung perubahan nilai-nilai itu juga.
Jika kita membobol WinDbg sejak awal dalam eksekusi kode pertama dan masuk sedikit ke dalam kode yang menghitung Normalize
vektor ed, kita bisa melihat perakitan berikut (lebih atau kurang - saya telah mengurangi beberapa bagian):
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]
dan setelah ~ 30 eksekusi (lebih lanjut tentang nomor ini nanti) ini akan menjadi kode:
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
Opcode yang berbeda, ekstensi yang berbeda - SSE vs AVX dan, saya kira, dengan opcode yang berbeda kita mendapatkan ketepatan perhitungan yang berbeda.
Jadi sekarang lebih banyak tentang mengapa? .NET Core (tidak yakin tentang versi - dengan asumsi 3.0 - tetapi telah diuji pada 2.1) memiliki sesuatu yang disebut "Kompilasi JIT Tiered". Apa yang dilakukannya adalah pada awalnya menghasilkan kode yang dihasilkan cepat, tetapi mungkin tidak super optimal. Hanya nanti ketika runtime mendeteksi bahwa kode tersebut sangat dimanfaatkan maka akan menghabiskan waktu tambahan untuk menghasilkan kode baru yang lebih dioptimalkan. Ini adalah hal baru di .NET Core sehingga perilaku seperti itu mungkin tidak diamati sebelumnya.
Juga mengapa 34 panggilan? Ini agak aneh karena saya berharap ini terjadi sekitar 30 eksekusi karena ini adalah ambang di mana kompilasi berjenjang dimulai. Konstanta dapat dilihat pada kode sumber coreclr . Mungkin ada beberapa variabilitas tambahan saat tendangan masuk.
Hanya untuk mengonfirmasi bahwa ini masalahnya, Anda dapat menonaktifkan kompilasi berjenjang dengan mengatur variabel lingkungan dengan mengeluarkan set COMPlus_TieredCompilation=0
dan memeriksa lagi eksekusi. Efek anehnya hilang.
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>
Apakah ini yang diharapkan, atau ini bug dalam bahasa / runtime?
Sudah ada bug yang dilaporkan untuk ini - Masalah 1119