2015-12-30 4 views
5

मैं परीक्षण कर रहा हूं कि मैं RyuJIT के साथ सिम निर्देशों का उपयोग करने से किस प्रकार की गति प्राप्त कर सकता हूं और मुझे कुछ डिस्सेप्लर निर्देश देख रहे हैं जिनकी मुझे उम्मीद नहीं है। मैं RyuJIT टीम के केविन फ्रीई से this blog post पर कोड और एक संबंधित पोस्ट here पर कोड का आधार बना रहा हूं। यहाँ समारोह है:सिमड इंट्रिनिक्स का उपयोग करते समय इन अतिरिक्त डिस्सेप्लर निर्देश क्या हैं?

static void AddPointwiseSimd(float[] a, float[] b) { 
    int simdLength = Vector<float>.Count; 
    int i = 0; 
    for (i = 0; i < a.Length - simdLength; i += simdLength) { 
     Vector<float> va = new Vector<float>(a, i); 
     Vector<float> vb = new Vector<float>(b, i); 
     va += vb; 
     va.CopyTo(a, i); 
    } 
} 

disassembly की धारा मैं Vector<float> में प्रतियां सरणी मूल्यों की क्वेरी हूँ। disassembly के अधिकांश कि केविन और साशा की पोस्ट में के समान है, लेकिन मैं कुछ अतिरिक्त निर्देश पर प्रकाश डाला गया है (मेरी उलझन में एनोटेशन के साथ) है कि उनके disassemblies में दिखाई नहीं देते:

;// Vector<float> va = new Vector<float>(a, i); 
    cmp eax,r8d    ; <-- Unexpected - Compare a.Length to i? 
    jae 00007FFB17DB6D5F  ; <-- Unexpected - Jump to range check failure 
    lea r10d,[rax+3] 
    cmp r10d,r8d 
    jae 00007FFB17DB6D5F 
    mov r11,rcx    ; <-- Unexpected - Extra register copy? 
    movups xmm0,xmmword ptr [r11+rax*4+10h ] 

;// Vector<float> vb = new Vector<float>(b, i); 
    cmp eax,r9d    ; <-- Unexpected - Compare b.Length to i? 
    jae 00007FFB17DB6D5F  ; <-- Unexpected - Jump to range check failure 
    cmp r10d,r9d 
    jae 00007FFB17DB6D5F 
    movups xmm1,xmmword ptr [rdx+rax*4+10h] 

नोट पाश रेंज की जांच के रूप में की उम्मीद है:

;// for (i = 0; i < a.Length - simdLength; i += simdLength) { 
    add eax,4 
    cmp r9d,eax 
    jg loop 

तो मैं क्यों eax करने के लिए अतिरिक्त तुलना देखते हैं पता नहीं है। क्या कोई यह समझा सकता है कि मैं इन अतिरिक्त निर्देशों को क्यों देख रहा हूं और यदि उनसे छुटकारा पाना संभव है।

यदि यह परियोजना सेटिंग्स से संबंधित है तो मुझे एक बहुत ही समान प्रोजेक्ट मिल गया है जो एक ही समस्या here on github दिखाता है (FloatSimdProcessor.HwAcceleratedSumInPlace() या UShortSimdProcessor.HwAcceleratedSumInPlaceUnchecked() देखें)।

उत्तर

10

मैं कोड पीढ़ी है कि मैं एक प्रोसेसर Haswell तरह AVX2 का समर्थन करता है कि के लिए देखते हैं, पर टिप्पणी करेंगे, यह एक समय में 8 तैरता स्थानांतरित कर सकते हैं:

00007FFA1ECD4E20 push  rsi 
00007FFA1ECD4E21 sub   rsp,20h 

00007FFA1ECD4E25 xor   eax,eax      ; i = 0 
00007FFA1ECD4E27 mov   r8d,dword ptr [rcx+8]   ; a.Length 
00007FFA1ECD4E2B lea   r9d,[r8-8]     ; a.Length - simdLength 
00007FFA1ECD4E2F test  r9d,r9d      ; if (i >= a.Length - simdLength) 
00007FFA1ECD4E32 jle   00007FFA1ECD4E75    ; then skip loop 

00007FFA1ECD4E34 mov   r10d,dword ptr [rdx+8]  ; b.Length 
00007FFA1ECD4E38 cmp   eax,r8d      ; if (i >= a.Length) 
00007FFA1ECD4E3B jae   00007FFA1ECD4E7B    ; then OutOfRangeException 
00007FFA1ECD4E3D lea   r11d,[rax+7]     ; i+7 
00007FFA1ECD4E41 cmp   r11d,r8d      ; if (i+7 >= a.Length) 
00007FFA1ECD4E44 jae   00007FFA1ECD4E7B    ; then OutOfRangeException 

00007FFA1ECD4E46 mov   rsi,rcx      ; move a[i..i+7] 
00007FFA1ECD4E49 vmovupd  ymm0,ymmword ptr [rsi+rax*4+10h] 

00007FFA1ECD4E50 cmp   eax,r10d      ; same as above 
00007FFA1ECD4E53 jae   00007FFA1ECD4E7B    ; but for b 
00007FFA1ECD4E55 cmp   r11d,r10d 
00007FFA1ECD4E58 jae   00007FFA1ECD4E7B 
00007FFA1ECD4E5A vmovupd  ymm1,ymmword ptr [rdx+rax*4+10h] 

00007FFA1ECD4E61 vaddps  ymm0,ymm0,ymm1    ; a[i..] + b[i...] 
00007FFA1ECD4E66 vmovupd  ymmword ptr [rsi+rax*4+10h],ymm0 

00007FFA1ECD4E6D add   eax,8       ; i += 8 
00007FFA1ECD4E70 cmp   r9d,eax      ; if (i < a.Length) 
00007FFA1ECD4E73 jg   00007FFA1ECD4E38    ; then loop 

00007FFA1ECD4E75 add   rsp,20h 
00007FFA1ECD4E79 pop   rsi 
00007FFA1ECD4E7A ret 

तो eax तुलना उन "परेशान करने के लिए बाध्य कर रहे हैं जाँच करता है "ब्लॉग पोस्ट के बारे में बात करते हैं। ब्लॉग पोस्ट एक अनुकूलित संस्करण प्रदान करता है जिसे वास्तव में लागू नहीं किया जाता है (अभी तक), वास्तविक कोड अभी एक ही समय में चलने वाली 8 फ्लोट्स की पहली और अंतिम अनुक्रमणिका दोनों की जांच करता है। ब्लॉग पोस्ट की टिप्पणी "उम्मीद है कि, हम अपने सीमा-जांच उन्मूलन कार्य को पर्याप्त रूप से मजबूत करेंगे" एक अपूर्ण कार्य है :)

mov rsi,rcx निर्देश ब्लॉग पोस्ट में भी मौजूद है और रजिस्टर में एक सीमा है संभाजक। शायद आरसीएक्स द्वारा एक महत्वपूर्ण रजिस्टर होने से प्रभावित, यह आमतौर पर स्टोर करता है। यह अनुकूलित करने के लिए काम करने के लिए पर्याप्त महत्वपूर्ण नहीं है, मुझे लगता है कि रजिस्टर-टू-रजिस्टर चाल 0 चक्र लेते हैं क्योंकि वे केवल पंजीकरण नामांकन को प्रभावित करते हैं।

ध्यान दें कि एसएसई 2 और एवीएक्स 2 के बीच का अंतर बदसूरत है, जबकि कोड एक समय में 8 फ्लोट्स चलाता है और जोड़ता है, यह वास्तव में उनमें से 4 का उपयोग करता है। Vector<float>.Count प्रोसेसर स्वाद के बावजूद 4 है, तालिका पर 2x perf छोड़कर। मुझे लगता है कि कार्यान्वयन विस्तार छुपा मुश्किल है।

संबंधित मुद्दे