2012-11-20 13 views
6

के साथ 32 बिट मान को घुमाया गया है, मैं 128 बिट रजिस्टर से प्रभावी तरीके से 4 बाइट निकालने का प्रयास कर रहा हूं। समस्या यह है कि प्रत्येक मान एक अलग 32 बिट {120,0,0,0,55,0,0,0,42,0,0,0,120,0,0,0} में है। मैं 128 बिट से 32 बिट को फॉर्म {120,55,42,120} रूपांतरित करना चाहता हूं।एसएसई निकालने के लिए केवल एसएसई 2

"कच्चे" कोड ऐसा दिखाई देता है:

__m128i byte_result_vec={120,0,0,0,55,0,0,0,42,0,0,0,120,0,0,0}; 
unsigned char * byte_result_array=(unsigned char*)&byte_result_vec; 
result_array[x]=byte_result_array[0]; 
result_array[x+1]=byte_result_array[4]; 
result_array[x+2]=byte_result_array[8]; 
result_array[x+3]=byte_result_array[12]; 

मेरे SSSE3 कोड है:

unsigned int * byte_result_array=...; 
__m128i byte_result_vec={120,0,0,0,55,0,0,0,42,0,0,0,120,0,0,0}; 
const __m128i eight_bit_shuffle_mask=_mm_set_epi8(1,1,1,1,1,1,1,1,1,1,1,1,0,4,8,12);  
byte_result_vec=_mm_shuffle_epi8(byte_result_vec,eight_bit_shuffle_mask); 
unsigned int * byte_result_array=(unsigned int*)&byte_result_vec; 
result_array[x]=byte_result_array[0]; 

मैं SSE2 के साथ इस कुशलता से कैसे कर सकते। एसएसएसई 3 या एसएसई 4 के साथ कोई बेहतर संस्करण है?

उत्तर

9

आप इस समाधान और रिवर्स ऑपरेशन के कुछ समाधानों के लिए a previous answer of mine देख सकते हैं।

SSE2 में विशेष रूप से जब आप पहली बार पर हस्ताक्षर किए 16-बिट पूर्णांक में 32-बिट पूर्णांक पैकिंग और संतृप्त द्वारा यह कर सकते हैं:

byte_result_vec = _mm_packs_epi32(byte_result_vec, byte_result_vec); 

फिर हम अहस्ताक्षरित 8 बिट मूल्यों में उन 16 बिट मूल्यों पैक

byte_result_vec = _mm_packus_epi16(byte_result_vec, byte_result_vec); 

हम तो अंत में रजिस्टर के निचले 32-बिट से हमारे मूल्यों ले जा सकते हैं:

int int_result = _mm_cvtsi128_si32(byte_result_vec); 
unsigned char* byte_result_array = (unsigned char*)&int_result; 
result_array[x] = byte_result_array[0]; 
result_array[x+1] = byte_result_array[1]; 
result_array[x+2] = byte_result_array[2]; 
result_array[x+3] = byte_result_array[3]; 
अहस्ताक्षरित संतृप्ति का उपयोग कर

संपादित करें: उपरोक्त मानते हैं कि 8-बिट शब्द प्रारंभ में अपने 32-बिट शब्दों के निम्न बाइट्स में हैं और शेष 0 एस से भरे हुए हैं, अन्यथा उनकी संतृप्त पैकिंग प्रक्रिया के दौरान क्लैंप हो जाएगी। इस प्रकार संचालन निम्नलिखित हैं:

   byte 15        0 
        0 0 0 D 0 0 0 C 0 0 0 B 0 0 0 A 

_mm_packs_epi32 -> 0 D 0 C 0 B 0 A 0 D 0 C 0 B 0 A 

_mm_packus_epi16 -> D C B A D C B A D C B A D C B A 
               ^^^^^^^ 

_mm_cvtsi128_si32 -> int DCBA, laid out in x86 memory as bytes A B C D 

-> reinterpreted as unsigned char array { A, B, C, D } 

uninterresting बाइट्स 0 रों शुरू में से भरा नहीं कर रहे हैं, तो आप पहले से उन्हें दूर मुखौटा करने के लिए है:

byte_result_vec = _mm_and_si128(byte_result_vec, _mm_set1_epi32(0x000000FF)); 

या अगर interresting बाइट में शुरू कर रहे हैं उच्च बाइट्स, तो आप पहले से कम बाइट्स में उन्हें शिफ्ट करने के लिए है:

byte_result_vec = _mm_srli_epi32(byte_result_vec, 24); 

या, यदि आप वास्तव में चाहते हैं { D, C, B, A } (जो compl नहीं है अपने प्रश्न से मुझे स्पष्ट रूप से स्पष्ट करें), ठीक है, तो यह असाइनमेंट में सरणी इंडेक्स को स्विच करने के लिए है (या वैकल्पिक रूप से प्रारंभिक एसएसई रजिस्टर पर 32-बिट शफल (_mm_shuffle_epi32) को वैकल्पिक रूप से प्रतिबिंबित करने के लिए)।

+0

यह एक सही जवाब है। मैं इसे दो बार कैसे बढ़ा सकता हूं? :) इसने मेरी बहुत मदद की। क्या आपको एसएसई 4 के साथ बेहतर तरीका पता है? –

+0

@ मार्टिन: एसएसएसई 3 और अधिक के साथ, आप बस एक पीएसएचयूएफबी चाहते हैं (जो आपके मौजूदा कोड को संकलित करना चाहिए)। –

+0

@ मार्टिन मैं एसएसई> 2 में अच्छी तरह से ज्ञात नहीं हूं, शायद मैं इसे देखने की कोशिश करूंगा। –

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