2017-08-24 13 views
5

क्या एसईएस रजिस्टर में एवीएक्स रजिस्टर के 64-बिट घटकों के उच्च/निम्न 32-बिट घटकों को दोबारा लगाने के लिए कोई आंतरिक या अन्य कारगर तरीका है? AVX2 का उपयोग कर एक समाधान ठीक है।__m256 के विषम तत्वों को __m128 में निकालने के लिए कुशल (Ryzen पर) तरीका?

अब तक मैं निम्नलिखित कोड का उपयोग कर रहा है, लेकिन प्रोफाइलर उस पर Ryzen 1800X धीमी है का कहना है:

// Global constant 
const __m256i gHigh32Permute = _mm256_set_epi32(0, 0, 0, 0, 7, 5, 3, 1); 

// ... 

// function code 
__m256i x = /* computed here */; 
const __m128i high32 = _mm256_castsi256_si128(_mm256_permutevar8x32_epi32(x), 
    gHigh32Permute); // This seems to take 3 cycles 
+1

तो क्या आप अजीब या यहां तक ​​कि क्रमांकित 32-बिट तत्व निकालना चाहते हैं? यानी AVX512 '_mm256_cvtepi64_epi32' (' vpmovqd') की तरह? मुझे नहीं लगता कि आप 3-चक्र विलंबता के साथ 1 शफल निर्देश को हराएंगे, क्योंकि लेन-क्रॉसिंग शफल हमेशा इंटेल CPU पर 3c विलंबता रखते हैं। आपके 'vpermd' समाधान में सिंगल-चक्र थ्रूपुट है। –

+0

यदि आपको तेज़ी से होने की आवश्यकता है, तो आपको आसपास के कोड को कम उपयोग करना होगा, या लेन-क्रॉसिंग या कुछ की आवश्यकता नहीं होगी! या हो सकता है कि किसी भी तरह से 256 बी परिणाम में दो स्रोतों को पैक करें, 'shufps' के साथ (सिवाय इसके कि यह लेन-क्रॉसिंग नहीं है, इसलिए यह आपकी समस्या का समाधान नहीं करता है, और वहां कोई' vpackqd' निर्देश नहीं है और पैक निर्देश लेन-क्रॉसिंग नहीं हैं।) –

+0

@ पीटरकॉर्डिस, हां, मैं 256-बिट रजिस्टर से 32-बिट तत्वों को 128-बिट रजिस्टर में विषम- या यहां तक ​​कि क्रमांकित 32-बिट तत्वों को निकालना चाहता हूं। AVX512 के संदर्भ के लिए धन्यवाद! मेरे पास रेजन 1800 एक्स पर नहीं है, लेकिन एक बार इसे माइग्रेट करने की उम्मीद है ... ये 32-बिट तत्व 64-बिट डबल के उच्च और निम्न भाग हैं, इसलिए मुझे आसपास के कोड को बदलने का कोई तरीका नहीं दिख रहा है । –

उत्तर

3

इंटेल पर, अपना कोड इष्टतम किया जाएगा। एक 1-यूओपी निर्देश आपको सबसे अच्छा मिलेगा। (यदि आप इनपुट/वीपी बाईपास विलंब के लिए किसी भी जोखिम से बचने के लिए vpermps का उपयोग करना चाहते हैं, तो यदि आपका इनपुट वेक्टर लोड या कुछ के बजाय pd निर्देश द्वारा बनाया गया था। पूर्णांक निर्देशों के इनपुट के रूप में एक एफपी शफल के परिणाम का उपयोग करना है आमतौर पर इंटेल पर ठीक है, लेकिन मुझे एक पूर्णांक शफल करने के लिए एक एफपी निर्देश के परिणाम को खिलाने के बारे में कम यकीन है।)

हालांकि इंटेल के लिए ट्यूनिंग होने पर, आप आसपास के कोड को बदलने का प्रयास कर सकते हैं ताकि आप नीचे 64 में घुमा सकें लेन-क्रॉसिंग शफल का उपयोग करने से बचने के लिए प्रत्येक 128 बी लेन के बिट्स। (तो फिर तुम सिर्फ vshufps ymm इस्तेमाल कर सकते हैं, या अगर ट्यूनिंग KNL के लिए, vpermilps के बाद से 2-इनपुट vshufps धीमी है।)

AVX512 साथ

, वहाँ _mm256_cvtepi64_epi32 (vpmovqd) कि कौन सी लेन भर तत्वों पैक, काट-छांट के साथ है।


Ryzen पर, लेन-पार शफ़ल धीमी हैं। Agner Fog में vpermd के लिए संख्या नहीं है, लेकिन वह vpermps (जो शायद आंतरिक रूप से एक ही हार्डवेयर का उपयोग करता है) 3 यूओएस, 5 सी विलंबता, प्रति 4 सी थ्रूपुट पर सूचीबद्ध करता है।

vextractf128 xmm, ymm, 1 रेजेन (1 सी विलंबता, 0.33 सी थ्रुपुट) पर बहुत ही कुशल है, यह आश्चर्यजनक नहीं है क्योंकि यह 256b रजिस्ट्रारों को पहले से ही दो 128 बी हिस्सों के रूप में ट्रैक करता है। shufps भी कुशल (1 सी विलंबता, 0.5 सी थ्रुपुट) है, और आपको दो 128 बी रजिस्ट्रारों को इच्छित परिणाम में घुमाने देगा।

यह आपको 2 vpermps शफल मास्क के लिए 2 रजिस्टरों को भी बचाता है जिनकी आपको अब आवश्यकता नहीं है।

तो मेरा सुझाव चाहते हैं:

__m256d x = /* computed here */; 

// Tuned for Ryzen. Sub-optimal on Intel 
__m128 hi = _mm_castpd_ps(_mm256_extractf128_pd(x, 1)); 
__m128 lo = _mm_castpd_ps(_mm256_castpd256_pd128(x)); 
__m128 odd = _mm_shuffle_ps(lo, hi, _MM_SHUFFLE(3,1,3,1)); 
__m128 even = _mm_shuffle_ps(lo, hi, _MM_SHUFFLE(2,0,2,0)); 

इंटेल पर, 2 की बजाय 3 शफ़ल का उपयोग कर आप इष्टतम प्रवाह क्षमता के 2/3rds देता है, पहला परिणाम के लिए 1c अतिरिक्त विलंबता के साथ।

+0

मैं मापा जाता है कि 'स्थिरांक __m128i high32 = _mm256_castsi256_si128 (_mm256_permutevar8x32_epi32 (_mm256_castpd_si256 (x), gHigh32Permute));' 'से स्थिरांक __m128i high32 = _mm_castps_si128 तेजी से होता है (_mm256_castps256_ps128 (_mm256_permutevar8x32_ps (_mm256_castpd_ps (x), gHigh32Permute)));' । तो शायद 'डबल' से 'फ्लोट' बाईपास के लिए जुर्माना भी है? –

+0

@ सर्जरोगैच: शफल के लिए असंभव। अधिक संभावना है, 'vpermd' बस' vpermps' से अलग प्रदर्शन करता है। (एग्नेर ने उन्हें दोनों सूचीबद्ध नहीं किया था इसलिए मुझे अनुमान लगाना पड़ा)। या जो भी आप परिणाम का उपभोग कर रहे हैं, वह एक पूर्णांक शफल से आने पर बेहतर होता है? एएमडी ने वास्तविक एफपी गणित निर्देशों के लिए फ्लोट बनाम डबल अंतर किया है, हालांकि, एग्नेर के मुताबिक। (लगभग हमेशा अप्रासंगिक है, लेकिन यह आंतरिक कार्यान्वयन के बारे में एक सुराग है, जैसे कि वेक्टर के साथ संग्रहीत कुछ अतिरिक्त टैग बिट्स हैं।) –

+0

'__m128 odd = _mm_shuffle_ps (hi) में 'hi' और' lo' को स्वैप नहीं किया जाना चाहिए , लो, _MM_SHUFFLE (3,1,3,1)); '? –

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