2013-12-11 5 views
5

मेरे पास एक बुलियन अभिव्यक्ति है जिसे मैंने एसएसई 2 में लागू करने में कामयाब रहा है। अब मुझे एवीएक्स में समांतरता वृद्धि (128 बिट सिम प्रकार से 256 तक) में एक अतिरिक्त कारक 2 का शोषण करने का प्रयास करना अच्छा लगेगा। हालांकि, एवीएक्स पूर्णांक ऑपरेशन का समर्थन नहीं करता है (जो AVX2 करता है, लेकिन मैं एक सैंडी ब्रिज प्रोसेसर पर काम कर रहा हूं, इसलिए यह वर्तमान में एक विकल्प नहीं है)। हालांकि, चूंकि AVX intrinsics for bitwise operations हैं। मैंने सोचा कि मैं अपने पूर्णांक प्रकारों को फ्लोट प्रकारों में परिवर्तित करके देख सकता हूं और देख सकता हूं कि यह काम करता है या नहीं।क्या AVX पर _m256 प्रकारों के लिए पूर्णांक बिटवाई ऑपरेशंस अनुकरण करने का कोई तरीका है?

__m256 ones = _mm256_set_ps(1,1,1,1,1,1,1,1); 
__m256 twos = _mm256_set_ps(2,2,2,2,2,2,2,2); 
__m256 result = _mm256_and_ps(ones, twos); 

मैं guetting कर रहा हूँ सभी 0 के रूप में मैं करना चाहिए:

पहला परीक्षण सफल रहा। Simularly दुक्की AND'ing बजाय मैं 2. का एक परिणाम मिलता है लेकिन जब 11 XOR 4 तदनुसार की कोशिश कर रहा:

__m256 elevens = _mm256_set_ps(11,11,11,11,11,11,11,11); 
__m256 fours = _mm256_set_ps(4,4,4,4,4,4,4,4); 
__m256 result2 = _mm256_xor_ps(elevens, fours); 

परिणाम है 6.46e -46 (यानी 0 के करीब) और नहीं कर रही 15. Simularly 11 या 4 मुझे 22 का मान देता है और 15 जैसा नहीं होना चाहिए। मुझे समझ में नहीं आता कि यह क्यों है। क्या यह एक बग या कुछ विन्यास है जो मुझे याद आ रही है?

मैं वास्तव में फ्लोट के साथ काम करने की मेरी परिकल्पना की उम्मीद कर रहा था जैसे कि वे काम नहीं करने के लिए पूर्णांक थे क्योंकि फ्लोट वैल्यू में शुरू होने वाले पूर्णांक वास्तव में सटीक मूल्य नहीं बल्कि निकटतम अनुमान हो सकता है। लेकिन फिर भी, मुझे मिलने वाले परिणाम से आश्चर्यचकित हूं।

क्या किसी को इस समस्या का हल है या क्या मुझे अपने सीपीयू को एवीएक्स 2 समर्थन प्राप्त करने के लिए अपग्रेड करना चाहिए?

+0

ऐसा लगता है कि आप 6.46e-46 प्राप्त करने के लिए एक फ्लोट के रूप में एक पूर्णांक प्रिंट कर रहे हैं। क्या आप सुनिश्चित हैं कि आपके 'printf()' स्वरूपण विनिर्देशक सही हैं? –

+0

मैं मुद्रण नहीं कर रहा था। मैंने अभी विजुअल स्टूडियो डीबगर में मूल्य की जांच की है। – Toby999

उत्तर

7

पहला परीक्षण दुर्घटना से काम करता था।

1 फ्लोट के रूप में 0x3f800000 है, 2 0x40000000 है। आम तौर पर, यह उस तरह से काम नहीं करेगा।

लेकिन आप इसे पूरी तरह से कर सकते हैं, आपको बस यह सुनिश्चित करना होगा कि आप सही बिट-पैटर्न के साथ काम कर रहे हैं। अपने पूर्णांक को फ्लोट में परिवर्तित न करें - उन्हें दोबारा डालें। यह _mm256_castsi256_ps जैसे इंट्रिनिक्स से मेल खाता है, या अपनी इंक को स्मृति में संग्रहीत करता है और उन्हें फ्लोट के रूप में पढ़ता है (जो उन्हें नहीं बदलता है, सामान्य रूप से केवल गणित परिचालनों की देखभाल करता है, मतलब, बाकी कच्चे बिट पैटर्न के साथ काम करता है, अपवादों की सूची जांचें जो एक निर्देश सुनिश्चित करने के लिए कर सकते हैं)।

+0

आह। धन्यवाद। यह समझ आता है। मैं इसे एक कोशिश देता हूं और अपने उत्तर को सही के रूप में चिह्नित करता हूं यदि यह काम करता है। – Toby999

+2

@ Toby999 लेकिन ध्यान रखें कि सभी मौजूदा इंटेल प्रोसेसर पर, बिटवाई लॉजिक निर्देशों के फ़्लोटिंग-पॉइंट संस्करणों में पूर्णांक संस्करणों के रूप में केवल 1/3 थ्रुपुट होता है। तो यदि आप इसे प्रदर्शन के लिए कर रहे हैं, तो आप दो बार सोचना चाहेंगे। यह तब भी बैकफायर हो सकता है जब तक आप डिकोडर बैंडविड्थ द्वारा सीमित न हों। – Mysticial

+2

सैंडी और आइवी ब्रिज पर, पूर्णांक एसएसई बिटवाइज तर्क किसी एक चक्र में 0, 1, या 5 बंदरगाहों में जा सकता है। यह प्रति चक्र 3 है।लेकिन फ्लोटिंग-पॉइंट एसएसई बिटवाइज लॉजिक केवल एक/चक्र में पोर्ट 5 पर जा सकता है। तो यह प्रति चक्र 1 तक ही सीमित है। हैसवेल पर, यह वही है, लेकिन इसमें AVX2 है - जो बिंदु को हल करता है। – Mysticial

4

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

//compiled and ran on an Ivy Bridge system with AVX but without AVX2 
#include <stdio.h> 
#include <immintrin.h> 
int main() { 
    int a[8] = {0, 2, 4, 6, 8, 10, 12, 14}; 
    int b[8] = {1, 1, 1, 1, 1, 1, 1, 1}; 
    int c[8]; 

    __m256i a8 = _mm256_loadu_si256((__m256i*)a); 
    __m256i b8 = _mm256_loadu_si256((__m256i*)b); 
    __m256i c8 = _mm256_castps_si256(
     _mm256_or_ps(_mm256_castsi256_ps(a8), _mm256_castsi256_ps(b8))); 
    _mm256_storeu_si256((__m256i*)c, c8); 
    for(int i=0; i<8; i++) printf("%d ", c[i]); printf("\n"); 
    //output: 1 3 5 7 9 11 13 15 
} 
बेशक

, के रूप में मिस्टिकल ने बताया ऐसा करने के लायक नहीं हो सकता है लेकिन इसका मतलब यह नहीं है कि आप यह नहीं कर सकते।

+0

आपके इनपुट के लिए धन्यवाद। यह सहायक था क्योंकि यह सही इंट्रिनिक्स विधियों को खोदने में समय ले रहा है। – Toby999

+0

वैरिएबल को संरेखित करने के विकल्प हैं इसलिए आपको असाइन किए गए लोड –

+0

@ LưuVĩnhPhúc से निपटने की आवश्यकता नहीं है, मैं काम कर रहा था धारणा है कि इससे कोई फर्क नहीं पड़ता। गठबंधन और असाइन किए गए लोड/स्टोर निर्देशों का थ्रूपुट और विलंबता गठबंधन स्मृति पर समान है। यह सिद्धांत है। लेकिन व्यवहार में मैं अभी भी एक अंतर देख रहा हूं इसलिए मैं आपसे सहमत हूं कि गठबंधन लोड निर्देशों का उपयोग किया जाना चाहिए। –

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