2015-11-12 6 views
6

पर 32 बिट पूर्णांक के लिए एसएसई निर्देश, मैं एक एसएसई निर्देश की तलाश में हूं जो __m128i में चार 32 बिट पूर्णांक के दो तर्क लेता है, संबंधित जोड़े के योग की गणना करता है और __m128i में दो 64 बिट पूर्णांक के रूप में परिणाम देता है।64 बिट

क्या इसके लिए कोई निर्देश है?

+0

[यहां एसएसई, एसएसई + एक्सओपी, एवीएक्स 2, एवीएक्स 512] के लिए 64 बिट से 128 बिट का समाधान है (http://stackoverflow.com/questions/27923192/practical-bignum-avx-sse-possible/27978043#27978043) । –

+0

आप ऐसा क्यों करना चाहते हैं? मैं समझता हूं कि आप 64 बी +64 बी + कैर क्यों चाहते हैं लेकिन 32 बी + 32 बी + कैर नहीं। –

उत्तर

6

कैर्री के साथ कोई एसएसई संचालन नहीं है। ऐसा करने का तरीका सबसे पहले 32-बिट पूर्णांक (punpckldq/punpckhdq) को सभी-शून्य शून्य सहायक वेक्टर का उपयोग करके 64-बिट पूर्णांक के 4 समूहों में अनपैक करना है, और फिर 64-बिट जोड़ी के अतिरिक्त उपयोग का उपयोग करना है।

+3

एसएसई 4.1 में कुछ पूर्णांक चौड़े निर्देश हैं जो इसे थोड़ा आसान और तेज़ बनाता है। – Mysticial

+1

@ मिस्टिकियल: हस्ताक्षरित पूर्णांक के लिए, यह वास्तव में 'pmovsx' के साथ एक * बहुत * आसान और तेज़ है। जैसा कि मैंने पहले सोचा था, उतना बड़ा नहीं है, क्योंकि साइन-मास्क के साथ अनपॅक करने के लिए मेरा जवाब लिखते हुए, और फिर एक साइन मास्क मिश्रण करने के बजाय मेरा जवाब लिखते समय मुझे बहुत अच्छा विचार था। लेकिन अगर आप स्मृति से लोड हो रहे हैं, तो 'pmovsx' बहुत अच्छा है, अन्यथा आपको ऊपरी आधे को साइन-विस्तार के लिए तैयार करने के लिए ऊपर ले जाने के लिए काम करना होगा। –

2

एसएसई केवल बाइट-> शब्द और शब्द-> शब्द के लिए है। (pmaddubsw (SSSE3) और pmaddwd (MMX/SSE2) है, जो खड़ी गुणा v1 * वी 2, तो क्षैतिज पड़ोसी जोड़े में जोड़ें।)

मैं क्या आप आउटपुट होना चाहते हैं पर स्पष्ट नहीं कर रहा हूँ। आपके पास 8 इनपुट पूर्णांक (4 के दो वैक्टर) हैं, और 2 आउटपुट पूर्णांक (दो का एक वेक्टर)। चूंकि कोई भी इंसिन नहीं है जो किसी भी प्रकार का 32 + 32 -> 64 बी वेक्टर जोड़ता है, चलिए देखते हैं कि वेक्टर के निम्न दो 32 बी तत्वों को 64b तक शून्य-विस्तारित या साइन-विस्तार कैसे करें। आप जो कुछ भी चाहते हैं उसे जोड़ सकते हैं, लेकिन ध्यान रखें कि कोई ऐड-क्षैतिज-जोड़े phaddq नहीं है, केवल लंबवत paddq है।

phaddd आप जो चाहते हैं उसके समान है, लेकिन चौड़ाई के बिना: परिणाम का कम आधा पहले ऑपरेंड में क्षैतिज जोड़े का योग है, उच्च आधा दूसरे ऑपरेंड में क्षैतिज जोड़े का योग है। यदि आपको उन सभी परिणामों की आवश्यकता है, तो यह केवल इतना ही उपयोगी है, और आप उन्हें आगे गठबंधन नहीं करेंगे। (यानी phadd को क्षैतिज रूप से एक वेक्टर संचयक को घटाने के बजाय चलाने के बजाए शफल और ऊर्ध्वाधर जोड़ने के लिए तेज़ी से तेज़ होता है। और यदि आप सबकुछ नीचे एक परिणाम तक जोड़ना चाहते हैं, तो सामान्य वर्टिकल रकम करें जब तक कि आप नीचे न हों एक रजिस्टर के लिए।) phaddd हार्डवेयर में paddd (एकल चक्र विलंबता और थ्रूपुट) जितनी तेजी से लागू किया जा सकता है, लेकिन यह किसी भी एएमडी या इंटेल CPU में नहीं है।


तरह Mysticial टिप्पणी की, SSE4.1 pmovzxdq/pmovsxdq आप वास्तव में क्या जरूरत है, और यहां तक ​​कि एक 64b स्मृति स्थान (दो 32b पूर्णांकों युक्त) से एक लोड के हिस्से के रूप मक्खी पर यह कर सकते हैं।

एसएसई 4.1 इंटेल पेन्रीन, 2 जी जनरल कोर 2 (45 एनएम मरने वाला कोर 2), नेहलेम से पहले पीढ़ी के साथ पेश किया गया था। उस से पुराने CPUs पर एक गैर-वेक्टर कोड पथ पर वापस गिरना ठीक हो सकता है, इस पर निर्भर करता है कि आप कितने पुराने और धीमे CPUs पर धीमे नहीं होने की परवाह करते हैं।


SSE4.1 के बिना:

अहस्ताक्षरित शून्य विस्तार आसान है। Pmdj की तरह उत्तर दिया, शून्य के साथ अनपैक करने के लिए बस punpck* लो और हाय का उपयोग करें।

यदि आपके पूर्णांक हस्ताक्षरित हैं, तो आपको मैन्युअल रूप से साइन-एक्सटेंशन करना होगा।

कोई psraq नहीं है, केवल psrad (पैक किए गए शिफ्ट दाएं अंकगणितीय दस्तावेज़) और psraw। यदि वहां था, तो आप स्वयं के साथ अनपॅक कर सकते थे और फिर 32 बी द्वारा अंकगणित सही शिफ्ट कर सकते थे।

इसके बजाय, हमें शायद वेक्टर उत्पन्न करने की आवश्यकता है जहां प्रत्येक तत्व इसके साइन बिट में बदल जाता है। फिर एक अनपॅक किए गए वेक्टर के साथ मिश्रण करें (लेकिन pblendw एसएसई 4 है।1 भी, इसलिए हमें por का उपयोग करना होगा)।

या बेहतर, मूल वेक्टर को साइन-मास्क के वेक्टर के साथ अनपैक करें।

# input in xmm0 
movdqa xmm1, xmm0 
movdqa xmm2, xmm0 
psrad  xmm0, 31  ; xmm0 = all-ones or all-zeros depending on sign of input elements. xmm1=orig ; xmm2=orig 
         ; xmm0 = signmask; xmm1=orig ; xmm2=orig 
punpckldq xmm1, xmm0 ; xmm1 = sign-extend(lo64(orig)) 
punpckhdq xmm2, xmm0 ; xmm2 = sign-extend(hi64(orig)) 

यह इंटेल एसएनबी या आईवीबी दोनों परिणामों के लिए 2 चक्र विलंबता के साथ चलना चाहिए। हैसवेल और बाद में केवल एक शफल बंदरगाह है (इसलिए वे समानांतर में punpck इन्स नहीं कर सकते हैं), इसलिए xmm2 को दूसरे चक्र के लिए देरी होगी। प्री-एसएनबी इंटेल सीपीयू आमतौर पर वेक्टर निर्देशों के साथ फ्रंटएंड (डिकोडर्स, आदि) पर बाधा डालते हैं, क्योंकि वे अक्सर 4 बी प्रति टन से अधिक औसत होते हैं।

प्रति के बजाय मूल स्थानांतरण निर्भरता श्रृंखला जो कुछ के लिए कदम उन्मूलन (रजिस्टर-नाम बदलने स्तर पर mov निर्देश से निपटने के बिना xmm0 पैदा करता है, CPU के लिए भी कम करता है तो वे शून्य विलंबता कर रहे हैं। इंटेल-केवल, और केवल पर आईवीबी और बाद में।) 3-ऑपरेंड एवीएक्स निर्देशों के साथ, आपको movdqa, या तीसरा रजिस्टर की आवश्यकता नहीं होगी, लेकिन फिर आप निम्न 6464 के लिए vpmovsx का उपयोग कर सकते हैं। साइन-विस्तार करने के लिए उच्च 64, तो आप शायद psrldq कम 64

या movhlps या punpckhqdq self,self उपयोग करने के लिए एक छोटी-से-एनकोड अनुदेश के बाइट-शिफ्ट होगी उच्च 64 नीचे। (या AVX2 एक 256b reg को vpmovsx, और फिर vextracti128 ऊपरी 128 में से केवल दो के निर्देश के साथ दोनों 128b परिणाम पाने के लिए।)


विपरीत जीपी से रजिस्टर बदलाव (जैसे sar eax, 31), वेक्टर बदलाव के बजाय गिनती को परिपूर्ण मास्किंग का। मूल प्रति बिट को एलएसबी (31 द्वारा स्थानांतरित) के रूप में छोड़कर इसकी प्रतिलिपि (32 तक स्थानांतरित) के रूप में छोड़कर ठीक काम करता है। इसका लाभ उन लोगों के लिए समझाए गए कोड के साथ एक बड़ी टिप्पणी की आवश्यकता नहीं है, जो psrad xmm0, 32 को देखते समय चिंता करेंगे।