Vì vậy, câu hỏi của tôi là, tại sao kết quả của việc gọi Vector2. Chuẩn hóa (v) thay đổi từ <0.9750545, -0.22196561> thành <0.97505456, -0.22196563> sau khi gọi nó 34 lần? 
Vì vậy, đầu tiên - tại sao sự thay đổi xảy ra. Sự thay đổi được quan sát bởi vì mã tính toán các giá trị đó cũng thay đổi.
Nếu chúng ta đột nhập vào WinDbg sớm trong các lần thực thi mã đầu tiên và đi sâu hơn một chút vào mã tính toán Normalizevectơ ed, chúng ta có thể thấy tập hợp sau (ít nhiều - tôi đã cắt giảm một số phần):
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]
và sau ~ 30 lần thực thi (sẽ nói thêm về số này sau) đây sẽ là mã:
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
Các mã khác nhau, các phần mở rộng khác nhau - SSE so với AVX và, tôi đoán, với các mã khác nhau, chúng tôi có được độ chính xác khác nhau của các phép tính.
Vì vậy, bây giờ nhiều hơn về lý do tại sao? .NET Core (không chắc chắn về phiên bản - giả sử 3.0 - nhưng nó đã được thử nghiệm trong 2.1) có một thứ gọi là "Biên dịch JIT theo tầng". Những gì nó làm là lúc đầu nó tạo ra mã được tạo ra nhanh, nhưng có thể không phải là siêu tối ưu. Chỉ sau này khi bộ thực thi phát hiện ra rằng mã được sử dụng nhiều, nó sẽ dành thêm thời gian để tạo mã mới, tối ưu hơn. Đây là một điều mới trong .NET Core vì vậy hành vi như vậy có thể không được quan sát trước đó.
Ngoài ra tại sao 34 cuộc gọi? Điều này hơi lạ vì tôi dự đoán điều này sẽ xảy ra trong khoảng 30 lần thực thi vì đây là ngưỡng mà quá trình biên dịch theo tầng bắt đầu. Có thể thấy hằng số trong mã nguồn của coreclr . Có thể có một số thay đổi bổ sung khi nó khởi động.
Chỉ cần xác nhận rằng đây là trường hợp, bạn có thể vô hiệu hóa trình biên dịch theo tầng bằng cách đặt biến môi trường bằng cách phát hành set COMPlus_TieredCompilation=0và kiểm tra lại việc thực hiện. Hiệu ứng lạ đã biến mất.
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>
  Đây có phải là dự kiến, hoặc đây là một lỗi trong ngôn ngữ / thời gian chạy?
Đã có một lỗi được báo cáo cho vấn đề này - Số 1119