टीएल; डीआर: सिस्टम को लपेटना क्यों है। न्यूमेरिक्स। वेक्टर महंगे हैं, और क्या मैं इसके बारे में कुछ भी कर सकता हूं?सिस्टम को लपेटने के लिए महंगा। Numerics.VectorX - क्यों?
00007FFDA3F94500 lea rax,[rcx+rdx]
00007FFDA3F94504 ret
और 86:
[MethodImpl(MethodImplOptions.NoInlining)]
private static long GetIt(long a, long b)
{
var x = AddThem(a, b);
return x;
}
private static long AddThem(long a, long b)
{
return a + b;
}
यह (64) में जीत जाएगा:
कोड का निम्न भाग पर विचार करें
00EB2E20 push ebp
00EB2E21 mov ebp,esp
00EB2E23 mov eax,dword ptr [ebp+10h]
00EB2E26 mov edx,dword ptr [ebp+14h]
00EB2E29 add eax,dword ptr [ebp+8]
00EB2E2C adc edx,dword ptr [ebp+0Ch]
00EB2E2F pop ebp
00EB2E30 ret 10h
अब, अगर मैं इस लपेट एक संरचना, उदाहरण के लिए
public struct SomeWrapper
{
public long X;
public SomeWrapper(long X) { this.X = X; }
public static SomeWrapper operator +(SomeWrapper a, SomeWrapper b)
{
return new SomeWrapper(a.X + b.X);
}
}
और GetIt
बदलें, उदा।
private static long GetIt(long a, long b)
{
var x = AddThem(new SomeWrapper(a), new SomeWrapper(b)).X;
return x;
}
private static SomeWrapper AddThem(SomeWrapper a, SomeWrapper b)
{
return a + b;
}
JITted परिणाम अब भी है बिल्कुल यदि स्थानीय प्रकार सीधे (AddThem
, और SomeWrapper
अतिभारित ऑपरेटर और निर्माता सभी inlined कर रहे हैं) का उपयोग कर के रूप में ही। जैसा सोचा था।
अब, अगर मैं इसे सिम-सक्षम प्रकारों के साथ आज़माता हूं, उदा। System.Numerics.Vector4
:
[MethodImpl(MethodImplOptions.NoInlining)]
private static Vector4 GetIt(Vector4 a, Vector4 b)
{
var x = AddThem(a, b);
return x;
}
इसे में JITted है:
00007FFDA3F94640 vmovupd xmm0,xmmword ptr [rdx]
00007FFDA3F94645 vmovupd xmm1,xmmword ptr [r8]
00007FFDA3F9464A vaddps xmm0,xmm0,xmm1
00007FFDA3F9464F vmovupd xmmword ptr [rcx],xmm0
00007FFDA3F94654 ret
हालांकि, अगर मैं Vector4
एक struct में (पहला उदाहरण के समान) लपेट:
public struct SomeWrapper
{
public Vector4 X;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public SomeWrapper(Vector4 X) { this.X = X; }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static SomeWrapper operator+(SomeWrapper a, SomeWrapper b)
{
return new SomeWrapper(a.X + b.X);
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static Vector4 GetIt(Vector4 a, Vector4 b)
{
var x = AddThem(new SomeWrapper(a), new SomeWrapper(b)).X;
return x;
}
मेरी कोड है एक बहुत अधिक में जोड़ा गया:
00007FFDA3F84A02 sub rsp,0B8h
00007FFDA3F84A09 mov rsi,rcx
00007FFDA3F84A0C lea rdi,[rsp+10h]
00007FFDA3F84A11 mov ecx,1Ch
00007FFDA3F84A16 xor eax,eax
00007FFDA3F84A18 rep stos dword ptr [rdi]
00007FFDA3F84A1A mov rcx,rsi
00007FFDA3F84A1D vmovupd xmm0,xmmword ptr [rdx]
00007FFDA3F84A22 vmovupd xmmword ptr [rsp+60h],xmm0
00007FFDA3F84A29 vmovupd xmm0,xmmword ptr [rsp+60h]
00007FFDA3F84A30 lea rax,[rsp+90h]
00007FFDA3F84A38 vmovupd xmmword ptr [rax],xmm0
00007FFDA3F84A3D vmovupd xmm0,xmmword ptr [r8]
00007FFDA3F84A42 vmovupd xmmword ptr [rsp+50h],xmm0
00007FFDA3F84A49 vmovupd xmm0,xmmword ptr [rsp+50h]
00007FFDA3F84A50 lea rax,[rsp+80h]
00007FFDA3F84A58 vmovupd xmmword ptr [rax],xmm0
00007FFDA3F84A5D vmovdqu xmm0,xmmword ptr [rsp+90h]
00007FFDA3F84A67 vmovdqu xmmword ptr [rsp+40h],xmm0
00007FFDA3F84A6E vmovdqu xmm0,xmmword ptr [rsp+80h]
00007FFDA3F84A78 vmovdqu xmmword ptr [rsp+30h],xmm0
00007FFDA3F84A7F vmovdqu xmm0,xmmword ptr [rsp+40h]
00007FFDA3F84A86 vmovdqu xmmword ptr [rsp+20h],xmm0
00007FFDA3F84A8D vmovdqu xmm0,xmmword ptr [rsp+30h]
00007FFDA3F84A94 vmovdqu xmmword ptr [rsp+10h],xmm0
00007FFDA3F84A9B vmovups xmm0,xmmword ptr [rsp+20h]
00007FFDA3F84AA2 vmovups xmm1,xmmword ptr [rsp+10h]
00007FFDA3F84AA9 vaddps xmm0,xmm0,xmm1
00007FFDA3F84AAE lea rax,[rsp]
00007FFDA3F84AB2 vmovupd xmmword ptr [rax],xmm0
00007FFDA3F84AB7 vmovdqu xmm0,xmmword ptr [rsp]
00007FFDA3F84ABD vmovdqu xmmword ptr [rsp+70h],xmm0
00007FFDA3F84AC4 vmovups xmm0,xmmword ptr [rsp+70h]
00007FFDA3F84ACB vmovupd xmmword ptr [rsp+0A0h],xmm0
00007FFDA3F84AD5 vmovupd xmm0,xmmword ptr [rsp+0A0h]
00007FFDA3F84ADF vmovupd xmmword ptr [rcx],xmm0
00007FFDA3F84AE4 add rsp,0B8h
00007FFDA3F84AEB pop rsi
00007FFDA3F84AEC pop rdi
00007FFDA3F84AED ret
ऐसा लगता है कि जेआईटी ने अब किसी कारण से फैसला किया है कि यह केवल रजिस्टरों का उपयोग नहीं कर सकता है, और इसके बजाय अस्थायी चर का उपयोग करता है, लेकिन मुझे समझ में नहीं आ रहा है कि क्यों। सबसे पहले मैंने सोचा कि यह एक संरेखण मुद्दा हो सकता है, लेकिन तब मुझे समझ में नहीं आ रहा है कि यह पहली बार xmm0 में क्यों लोड हो रहा है और फिर स्मृति के लिए यात्रा करने का निर्णय ले रहा है।
यहां क्या हो रहा है? और सबसे महत्वपूर्ण बात यह है कि, क्या मैं इसे ठीक कर सकता हूं?
कारण यह है कि मैं इस तरह की संरचना को लपेटना चाहता हूं कि मेरे पास लॉटसी कोड का है जो एपीआई का उपयोग करता है जिसका कार्यान्वयन कुछ सिमड भलाई से लाभान्वित होगा।
संपादित: तो, कुछ coreclr source में चारों ओर खुदाई के बाद, मुझे पता चला है कि यह वास्तव System.Numerics कक्षाओं के बारे में कुछ खास नहीं है। मुझे बस अपनी विधियों में System.Numerics.JitIntrinsic
विशेषता जोड़नी है। इसके बाद जेआईटी मेरे कार्यान्वयन को अपने आप से बदल देगा। JitIntrinsic
निजी है? कोई समस्या नहीं, बस इसे कॉपी + पेस्ट करें। मूल प्रश्न अभी भी बनी हुई है (भले ही अब मेरे पास कोई कामकाज हो)।
सभी फ़ील्ड तैरते हैं। सिमड केस को छोड़कर स्ट्रक्चर रैपिंग को रेखांकित किया गया है। आपके उदाहरण में कोड आम तौर पर आवश्यक नहीं है। मेरा सवाल यह है कि यह सिम मामले में क्यों टूट जाता है? (जैसा कि मैंने अपने अपडेट में लिखा था, मैं एक स्वीकार्य कामकाज खोजने में सक्षम था) – Krumelur