इंटेल पर, अपना कोड इष्टतम किया जाएगा। एक 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 अतिरिक्त विलंबता के साथ।
तो क्या आप अजीब या यहां तक कि क्रमांकित 32-बिट तत्व निकालना चाहते हैं? यानी AVX512 '_mm256_cvtepi64_epi32' (' vpmovqd') की तरह? मुझे नहीं लगता कि आप 3-चक्र विलंबता के साथ 1 शफल निर्देश को हराएंगे, क्योंकि लेन-क्रॉसिंग शफल हमेशा इंटेल CPU पर 3c विलंबता रखते हैं। आपके 'vpermd' समाधान में सिंगल-चक्र थ्रूपुट है। –
यदि आपको तेज़ी से होने की आवश्यकता है, तो आपको आसपास के कोड को कम उपयोग करना होगा, या लेन-क्रॉसिंग या कुछ की आवश्यकता नहीं होगी! या हो सकता है कि किसी भी तरह से 256 बी परिणाम में दो स्रोतों को पैक करें, 'shufps' के साथ (सिवाय इसके कि यह लेन-क्रॉसिंग नहीं है, इसलिए यह आपकी समस्या का समाधान नहीं करता है, और वहां कोई' vpackqd' निर्देश नहीं है और पैक निर्देश लेन-क्रॉसिंग नहीं हैं।) –
@ पीटरकॉर्डिस, हां, मैं 256-बिट रजिस्टर से 32-बिट तत्वों को 128-बिट रजिस्टर में विषम- या यहां तक कि क्रमांकित 32-बिट तत्वों को निकालना चाहता हूं। AVX512 के संदर्भ के लिए धन्यवाद! मेरे पास रेजन 1800 एक्स पर नहीं है, लेकिन एक बार इसे माइग्रेट करने की उम्मीद है ... ये 32-बिट तत्व 64-बिट डबल के उच्च और निम्न भाग हैं, इसलिए मुझे आसपास के कोड को बदलने का कोई तरीका नहीं दिख रहा है । –