2016-12-26 8 views
6

मैं एसएसई प्रकारों के बीच रूपांतरण लागू कर रहा हूं और मैंने पाया कि पूर्व-एसएसई 4.1 लक्ष्यों के लिए int8-> int64 चौड़ा रूपांतरण लागू करना बोझिल है।एसएसई के साथ int8/int64 रूपांतरण कुशलतापूर्वक कैसे करें?

सीधा कार्यान्वयन होगा:

inline __m128i convert_i8_i64(__m128i a) 
{ 
#ifdef __SSE4_1__ 
    return _mm_cvtepi8_epi64(a); 
#else 
    a = _mm_unpacklo_epi8(a, a); 
    a = _mm_unpacklo_epi16(a, a); 
    a = _mm_unpacklo_epi32(a, a); 
    return _mm_srai_epi64(a, 56); // missing instrinsic! 
#endif 
} 

लेकिन _mm_srai_epi64 के बाद से अस्तित्व में नहीं है जब तक AVX-512, वहाँ इस बिंदु पर दो विकल्प हैं:

  • _mm_srai_epi64, या
  • को लागू करने एक अलग तरीके से convert_i8_i64 लागू करना।

मुझे यकीन नहीं है कि कौन सा सबसे कुशल समाधान होगा। कोई उपाय?

उत्तर

4

अनपॅकिंग इंट्रिनिक्स का उपयोग यहां एक मजेदार तरीके से किया जाता है। वे साइन-एक्सटेंशन जोड़ने के बजाय डेटा को "डुप्लिकेट" करते हैं, जैसा कि कोई उम्मीद करेगा। उदाहरण के लिए, पहली यात्रा से पहले आप अपने रजिस्टर में निम्नलिखित

x x x x x x x x x x x x x x a b 

आप a और b से 16 बिट्स परिवर्तित, तो आप इस मिलना चाहिए:

x x x x x x x x x x x x A a B b 

यहाँ A और B sign- हैं a और b के एक्सटेंशन, यानी, दोनों या तो 0 या -1 हैं।

इसके बजाय इस बात का

, अपने कोड देता है

x x x x x x x x x x x x a a b b 

और फिर आप सही स्थानांतरण द्वारा उचित परिणाम के लिए परिवर्तित।

हालांकि, आप "unpack" intrinsics में दो बार एक ही ऑपरेंड का उपयोग करने के लिए बाध्य नहीं हैं।

x x x x x x x x x x x x x x a b 
x x x x x x x x x x x x x x A B 

यही कारण है: यदि आप "पैक" निम्नलिखित दो रजिस्टरों आप इच्छित परिणाम प्राप्त कर सकते हैं

a = _mm_unpacklo_epi8(a, _mm_srai_epi8(a, 8)); 

(अगर है कि _mm_srai_epi8 आंतरिक वास्तव में अस्तित्व में)


आप कर सकते हैं अपने रूपांतरण के अंतिम चरण में एक ही विचार लागू करें। आप "खोल" के लिए निम्न दो रजिस्टरों हैं:

x x x x x x x x A A A a B B B b 
x x x x x x x x A A A A B B B B 

उन्हें प्राप्त करने के लिए, राइट-शिफ्ट 32-बिट डेटा:

_mm_srai_epi32(a, 24) 
_mm_srai_epi32(a, 32) 

तो पिछले "खोल" है

_mm_unpacklo_epi32(_mm_srai_epi32(a, 24), _mm_srai_epi32(a, 32)); 
2

एसएसएसई 3 के साथ, आप अधिकांश अनपैक से बचने के लिए pshufb का उपयोग कर सकते हैं।अनातोली के a/A संकेतन का उपयोग करना:

;; input in xmm0    ;; x x x x x x x x | x x x x x x a b 
pshufb xmm0, [low_to_upper] ;; a 0 0 0 0 0 0 0 | b 0 0 0 0 0 0 0 
psrad xmm0, 24    ;; A A A a 0 0 0 0 | B B B b 0 0 0 0 
pshufb xmm0, [bcast_signextend]; A A A A A A A a | B B B B B B B b 

SSSE3 के बिना, मुझे लगता है कि आप PSHUFLW, PSHUFD साथ कुछ करने के लिए सक्षम हो सकता है, और शायद PUNPCK चरणों में से कुछ के बजाय POR। लेकिन मैंने जो भी सोचा है, वह वास्तव में अनपॅक से बेहतर नहीं है जब तक कि आप Core2 या अन्य धीमे-शफल CPU पर नहीं हैं, जहां pshuflwpunpcklbw से तेज़ है।

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