तो मेरा सवाल यह है कि 34 बार कॉल करने के बाद, वेक्टर 0.. सामान्य (v) कॉलिंग का परिणाम <0.9750545, -0.22196561> से <0.97505456, -0.22196563 तक क्यों बदल जाता है?
तो पहला - परिवर्तन क्यों होता है। परिवर्तित मनाया जाता है क्योंकि कोड जो उन मानों की गणना करता है वे भी बदल जाते हैं।
यदि हम कोड के पहले निष्पादन में WinDbg पर जल्दी टूट जाते हैं और कोड में थोड़ा नीचे जाते हैं जो कि Normalize
एड वेक्टर की गणना करता है , तो हम निम्नलिखित असेंबली को देख सकते हैं (अधिक या कम - मैंने कुछ हिस्सों को काट दिया है):
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
अलग-अलग ऑपकोड, अलग-अलग एक्सटेंशन - एसएसई बनाम एवीएक्स और, मुझे लगता है कि विभिन्न ऑपकोड के साथ हमें गणना की अलग-अलग सटीकता मिलती है।
तो अब इसके बारे में और क्यों? .NET कोर (संस्करण के बारे में निश्चित नहीं है - 3.0 मान - लेकिन यह 2.1 में परीक्षण किया गया था) में कुछ ऐसा है जिसे "Tiered JIT संकलन" कहा जाता है। यह शुरुआत में ऐसा कोड बनाता है जो तेजी से उत्पन्न होता है, लेकिन यह सुपर इष्टतम नहीं हो सकता है। बाद में जब रनटाइम का पता चलता है कि कोड अत्यधिक उपयोग किया जाता है तो यह नया, अधिक अनुकूलित कोड उत्पन्न करने के लिए कुछ अतिरिक्त समय बिताएगा। यह .NET कोर में एक नई बात है इसलिए ऐसा व्यवहार पहले नहीं देखा जा सकता है।
इसके अलावा 34 कॉल क्यों? यह थोड़ा अजीब है क्योंकि मैं यह उम्मीद करूंगा कि यह लगभग 30 निष्पादन के साथ हो सकता है क्योंकि यह वह सीमा है जिस पर टियर कंपाइल किक करता है । कॉरलेर के स्रोत कोड में निरंतर देखा जा सकता है । हो सकता है कि इसमें किक करने पर कुछ अतिरिक्त परिवर्तनशीलता हो।
बस यह पुष्टि करने के लिए कि यह मामला है, आप जारी करने set COMPlus_TieredCompilation=0
और फिर से निष्पादन की जाँच करके पर्यावरण चर सेट करके tiered संकलन को अक्षम कर सकते हैं । विचित्र प्रभाव पड़ा है।
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