ดังนั้นคำถามของฉันคือทำไมผลลัพธ์ของการเรียก Vector2. Normal (v) เปลี่ยนจาก <0.9750545, -0.22196561> เป็น <0.97505456, -0.22196563> หลังจากเรียกมัน 34 ครั้ง?
ดังนั้นก่อน - ทำไมการเปลี่ยนแปลงเกิดขึ้น มีการสังเกตการเปลี่ยนแปลงเนื่องจากรหัสที่คำนวณค่าเหล่านั้นก็เปลี่ยนแปลงเช่นกัน
ถ้าเราบุกเข้าไปใน 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
opcodes ที่แตกต่างกัน, ส่วนขยายที่แตกต่างกัน - SSE vs AVX และ, ฉันเดา, ด้วย opcodes ที่แตกต่างกันเราได้รับความแม่นยำที่แตกต่างกันของการคำนวณ
ดังนั้นเพิ่มเติมเกี่ยวกับสาเหตุ .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