2012-05-17 16 views
6

मेरे पास बहुत लंबे बाइट एरे हैं जिन्हें short (या int) के गंतव्य सरणी में जोड़ा जाना आवश्यक है। क्या ऐसे एसएसई निर्देश मौजूद हैं? या शायद उनके सेट?एसएसई निर्देश: बाइट + लघु

उत्तर

6

आपको 8 बिट मानों के प्रत्येक वेक्टर को 16 बिट मानों के दो वैक्टरों में अनपैक करने की आवश्यकता है और फिर उन्हें जोड़ें।

__m128i v = _mm_set_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0); 
__m128i vl = _mm_unpacklo_epi8(v, _mm_set1_epi8(0)); // vl = { 7, 6, 5, 4, 3, 2, 1, 0 } 
__m128i vh = _mm_unpackhi_epi8(v, _mm_set1_epi8(0)); // vh = { 15, 14, 13, 12, 11, 10, 9, 8 } 

जहां v 16 x 8 बिट मूल्यों और vl का एक वेक्टर है, vh 8 x 16 बिट मूल्यों के दो पैक वैक्टर हैं।

ध्यान दें कि मुझे लगता है कि 8 बिट मानों को हस्ताक्षरित किया गया है, इसलिए 16 बिट्स को अनपॅक करने पर उच्च बाइट 0 पर सेट किया गया है (यानी कोई साइन एक्सटेंशन नहीं)।

यदि आप इन बहुत से वैक्टरों को जोड़ना चाहते हैं और 32 बिट परिणाम प्राप्त करना चाहते हैं तो _mm_madd_epi16 का उपयोग गुणक के साथ एक उपयोगी चाल है, उदाहरण के लिए

__m128i vsuml = _mm_set1_epi32(0); 
__m128i vsumh = _mm_set1_epi32(0); 
__m128i vsum; 
int sum; 

for (int i = 0; i < N; i += 16) 
{ 
    __m128i v = _mm_load_si128(&x[i]); 
    __m128i vl = _mm_unpacklo_epi8(v, _mm_set1_epi8(0)); 
    __m128i vh = _mm_unpackhi_epi8(v, _mm_set1_epi8(0)); 
    vsuml = _mm_add_epi32(vsuml, _mm_madd_epi16(vl, _mm_set1_epi16(1))); 
    vsumh = _mm_add_epi32(vsumh, _mm_madd_epi16(vh, _mm_set1_epi16(1))); 
} 
// do horizontal sum of 4 partial sums and store in scalar int 
vsum = _mm_add_epi32(vsuml, vsumh); 
vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 8)); 
vsum = _mm_add_epi32(vsum, _mm_srli_si128(vsum, 4)); 
sum = _mm_cvtsi128_si32(vsum); 
+1

मेरी अज्ञानता क्षमा करें लेकिन क्या आप वाकई सही हैं? यह बनाम = _mm_madd_epi16 (vh, _mm_set1_epi16 (1)); बनाम के पिछले मूल्य मिटा देंगे। – Alexandros

+0

@Alexandros: आप सही हैं, और मुझे वहां कम से कम एक और गलती भी दिखाई देती है - मुझे लगता है कि जब मैंने यह उत्तर लिखा था तो मुझे जल्दबाजी में होना चाहिए - मैं जल्द ही कोड ठीक कर दूंगा, लेकिन मैं यात्रा कर रहा हूं वर्तमान। –

+1

धन्यवाद पॉल, जल्दी नहीं। आपने अतीत में मुझे बहुत मदद की है, इसलिए जब भी आप इसे ठीक कर सकते हैं, इसे ठीक करें। यात्रा मंगलमय हो!! – Alexandros

0

आप के बजाय अपने बाइट वैक्टर पंजीकरण का विस्तार करने की जरूरत है शून्य का विस्तार, pmovsxbw (_mm_cvtepi8_epi16) का उपयोग करें। अनपैक हाय/लो निर्देशों के विपरीत, आप केवल srcovsx को कम से कम/तिमाही/एक src रजिस्टर के आठवें से ही कर सकते हैं।

हालांकि आप सीधे स्मृति से pmovsx कर सकते हैं, भले ही आंतरिक वास्तव में यह बेकार बनाते हैं। चूंकि शफ़ल थ्रूपुट अधिकतर CPUs पर लोड थ्रूपुट से अधिक सीमित है, इसलिए संभवतः एक लोड + तीन शफल करने के लिए दो लोड + pmovsx करना बेहतर होता है।

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