2012-06-29 17 views
5

का उपयोग कर 128-बिट रोटेशन मैं नियॉन इंट्रिनिक्स का उपयोग करके अपना कोड अनुकूलित करने की कोशिश कर रहा हूं। मेरे पास 128-बिट सरणी (8 प्रत्येक uint16_t) पर 24-बिट रोटेशन है।एआरएम नियॉन इंट्रिनिक्स

यहाँ मेरी ग कोड है:

uint16_t rotated[8]; 
uint16_t temp[8]; 
uint16_t j; 
for(j = 0; j < 8; j++) 
{ 
    //Rotation <<< 24 over 128 bits (x << shift) | (x >> (16 - shift) 
    rotated[j] = ((temp[(j+1) % 8] << 8) & 0xffff) | ((temp[(j+2) % 8] >> 8) & 0x00ff); 
} 

मैं जीसीसी प्रलेखन Neon Intrinsics के बारे में जांच की है और यह वेक्टर रोटेशन के लिए निर्देश नहीं है। इसके अलावा, मैंने vshlq_n_u16(temp, 8) का उपयोग करके ऐसा करने का प्रयास किया है, लेकिन uint16_t शब्द के बाहर स्थानांतरित सभी बिट्स खो गए हैं।

नियॉन इंट्रिनिक्स का उपयोग करके इसे कैसे प्राप्त किया जाए? वैसे जीसीसी नियॉन इंट्रिनिक्स के बारे में एक बेहतर दस्तावेज है?

+0

'armcc' में' __ror' आंतरिक – ouah

+0

'आरओआर' एआरएम निर्देश के साथ इनलाइन असेंबली का उपयोग करने के बारे में क्या है? – ouah

+0

मैं असेंबली से बचना पसंद करता हूं। जिस तरह से मैं जीसीसी का उपयोग कर रहा हूं तो कोई armcc नहीं! – Kami

उत्तर

6

कुछ Arm Community Blogs पर पढ़ने के बाद, मैं इस पाया है:

Neon Arm Bitwise Rotation

VEXT: निकालें VEXT मौजूदा वैक्टर की एक जोड़ी से बाइट्स की एक नई वेक्टर निकालता है। नए वेक्टर में बाइट्स पहले ऑपरेंड के शीर्ष से और दूसरे ऑपरेंड के नीचे से हैं। यह आपको उन तत्वों वाले एक नए वेक्टर का उत्पादन करने की अनुमति देता है जो मौजूदा वैक्टर की एक जोड़ी को जोड़ता है। VEXT का उपयोग एफआईआर फिल्टर में उपयोगी, दो वैक्टरों से डेटा पर एक चलती खिड़की को लागू करने के लिए किया जा सकता है। क्रमपरिवर्तन के लिए, यह दोनों इनपुट ऑपरेटरों के लिए एक ही वेक्टर का उपयोग करते समय बाइट-वार घुमावदार ऑपरेशन अनुकरण करने के लिए भी उपयोग किया जा सकता है।

निम्नलिखित नियॉन जीसीसी आंतरिक चित्र में प्रदान की विधानसभा के रूप में ही कार्य करता है:

uint16x8_t vextq_u16 (uint16x8_t, uint16x8_t, const int) 

तो एक पूर्ण 128bit वेक्टर (प्रत्येक तत्व खत्म नहीं) से अधिक 24bit रोटेशन से किया जा सकता है निम्नलिखित:

uint16x8_t input; 
uint16x8_t t0; 
uint16x8_t t1; 
uint16x8_t rotated; 

t0 = vextq_u16(input, input, 1); 
t0 = vshlq_n_u16(t0, 8); 
t1 = vextq_u16(input, input, 2); 
t1 = vshrq_n_u16(t1, 8); 
rotated = vorrq_u16(t0, t1); 
+0

जब तक मैं कुछ याद नहीं कर रहा हूं, यह एक निर्देश में पूरे घूर्णन को करने के लिए 'vextq_u8' की तुलना में अधिक जटिल है। –

4

मैं 100% निश्चित नहीं हूं लेकिन मुझे नहीं लगता कि नीयन ने घूर्णन निर्देशों को घुमाया है।

आप रोटेशन आपरेशन यदि आप बाईं पारी, एक सही गंदगी और एक या साथ की आवश्यकता होती है, उदा .:

uint8_t ror(uint8_t in, int rotation) 
{ 
    return (in >> rotation) | (in << (8-rotation)); 
} 

बस बाईं पारी, सही बकवास और या के लिए नियॉन intrinsics साथ भी ऐसा ही रचना कर सकते हैं।

uint16x8_t temp; 
uint8_t rot; 

uint16x8_t rotated = vorrq_u16 (vshlq_n_u16(temp, rot) , vshrq_n_u16(temp, 16 - rot)); 

http://en.wikipedia.org/wiki/Circular_shift "परिपत्र बदलाव को लागू करने।" देखें

यह लेन के अंदर मूल्यों को घुमाएगा। यदि आप लेन को घूमना चाहते हैं तो वे अन्य उत्तर में वर्णित VEXT का उपयोग करें।

+0

मैं नहीं पूछ रहा हूं कि सी में गोलाकार रोटेशन कैसे करें! मैं पूछ रहा हूं कि नियॉन इंट्रिनिक्स का उपयोग करके इसे कैसे किया जाए! – Kami

+0

ठीक है, मैंने वास्तविक आंतरिक कॉल जोड़ा है। –

+0

यह ओपी के उत्तर से कम बुरा है (5 के बजाय 3 निर्देश), लेकिन बाइट-शिफ्ट निर्देशों की तुलना में 'vext.8' वास्तव में धीमा है, यह अभी भी अक्षम है। –

2

उपयोग vext.8 के साथ ही एक वेक्टर concat और आप 16-बाइट खिड़की (इस मामले 3 बाइट्स की भरपाई में) जो आप चाहते देने के लिए।

संकलक खुश रखने के लिए intrinsics requires casting साथ ऐसा करने से, लेकिन यह अभी भी एक एकल अनुदेश है:

#include <arm_neon.h> 

uint16x8_t byterotate3(uint16x8_t input) { 
    uint8x16_t tmp = vreinterpretq_u8_u16(input); 
    uint8x16_t rotated = vextq_u8(tmp, tmp, 16-3); 
    return vreinterpretq_u16_u8(rotated); 
} 

g++5.4 -O3 -march=armv7-a -mfloat-abi=hard -mfpu=neon (on Godbolt) यह करने के लिए यह संकलित:

byterotate3(__simd128_uint16_t): 
    vext.8 q0, q0, q0, #13 
    bx  lr 

16- की संख्या है, 3 का मतलब है कि हम 3 बाइट्स द्वारा बाएं घुमाएंगे। (इसका मतलब है कि हम बाएं वेक्टर से 13 बाइट और दाएं वेक्टर से 3 बाइट्स लेते हैं, इसलिए यह 13 तक दाएं-घुमावदार भी है)।


संबंधित: palignr (SSSE3 में जोड़ा): 86 भी निर्देश है कि दो रजिस्टरों के संयोजन में एक स्लाइडिंग खिड़की लेता है।


शायद मैं नियोन के बारे में कुछ याद कर रहा हूँ, लेकिन मुझे समझ नहीं आता क्यों ओ पी के स्वयं के जवाब vext.16 (vextq_u16) है, जो 16-बिट के विवरण का स्तर है उपयोग कर रहा है। यह एक अलग निर्देश भी नहीं है, केवल vext.8 के लिए एक उपनाम है जो अतिरिक्त विषम संख्याओं की आवश्यकता के लिए अजीब संख्याबद्ध गणना का उपयोग करना असंभव बनाता है। The manual for vext.8 says:

VEXT छद्म अनुदेश

आप इस मामले में 16, 32, या 64 के बजाय 8 के एक डेटा-प्रकार निर्दिष्ट कर सकते हैं, #imm halfwords शब्दों को doublewords बजाय संदर्भित करता है, या बाइट्स का जिक्र करते हुए, और अनुमत श्रेणियां संगत रूप से कम हो गई हैं।

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