c++ - एसएसई निर्देशों का उपयोग करना




optimization assembly (10)

  1. एसएसई निर्देश प्रोसेसर विशिष्ट हैं। आप देख सकते हैं कि कौन सा प्रोसेसर विकिपीडिया पर एसएसई संस्करण का समर्थन करता है।
  2. यदि एसएसई कोड तेज होगा या नहीं, तो कई कारकों पर निर्भर करता है: पहला यह है कि समस्या स्मृति-बाध्य या सीपीयू-बाध्य है या नहीं। अगर मेमोरी बस बाधा है तो एसएसई ज्यादा मदद नहीं करेगा। अपनी पूर्णांक गणना को सरल बनाने का प्रयास करें, अगर यह कोड को तेज़ी से बनाता है, तो शायद यह सीपीयू-बाउंड है, और आपके पास इसे तेज करने का एक अच्छा मौका है।
  3. ध्यान रखें कि सिम-कोड लिखना सी ++ - कोड लिखने से बहुत कठिन है, और परिणामी कोड बदलने के लिए बहुत कठिन है। हमेशा सी ++ कोड को अद्यतित रखें, आप इसे एक टिप्पणी के रूप में और अपने असेंबलर कोड की शुद्धता की जांच कर सकते हैं।
  4. आईपीपी जैसी लाइब्रेरी का उपयोग करने के बारे में सोचें, जो विभिन्न प्रोसेसर के लिए अनुकूलित सामान्य निम्न-स्तर सिमड ऑपरेशंस लागू करता है।

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


इस तरह की समस्या एक आदर्श उदाहरण है जहां एक अच्छा निम्न स्तर प्रोफाइलर आवश्यक है। (VTune की तरह कुछ) यह आपको अपने हॉटस्पॉट कहां झूठ बोलने का एक और अधिक सूचित विचार दे सकता है।

मेरा अनुमान है कि, आप जो वर्णन करते हैं, वह यह है कि आपका हॉटस्पॉट शायद शाखा भविष्यवाणी विफलताओं के परिणामस्वरूप न्यूनतम / अधिकतम गणनाओं के परिणामस्वरूप / else का उपयोग कर रहा है। इसलिए, सिमड इंट्रिनिक्स का उपयोग करने से आपको न्यूनतम / अधिकतम निर्देशों का उपयोग करने की अनुमति मिलनी चाहिए, हालांकि, इसके बजाय केवल एक शाखा रहित न्यूनतम / अधिकतम कैलक्यूलेशन का उपयोग करने की कोशिश करना उचित हो सकता है। इससे कम दर्द वाले अधिकांश लाभ प्राप्त हो सकते हैं।

कुछ इस तरह:

inline int 
minimum(int a, int b)
{
  int mask = (a - b) >> 31;
  return ((a & mask) | (b & ~mask));
}

कोड लिखें जो संकलक को समझने में मदद करता है कि आप क्या कर रहे हैं। जीसीसी एसएसई कोड को समझ और अनुकूलित करेगा जैसे कि:

typedef union Vector4f
{
        // Easy constructor, defaulted to black/0 vector
    Vector4f(float a = 0, float b = 0, float c = 0, float d = 1.0f):
        X(a), Y(b), Z(c), W(d) { }

        // Cast operator, for []
    inline operator float* ()
    { 
        return (float*)this;
    }

        // Const ast operator, for const []
    inline operator const float* () const
    { 
        return (const float*)this;
    }

    // ---------------------------------------- //

    inline Vector4f operator += (const Vector4f &v)
    {
        for(int i=0; i<4; ++i)
            (*this)[i] += v[i];

        return *this;
    }

    inline Vector4f operator += (float t)
    {
        for(int i=0; i<4; ++i)
            (*this)[i] += t;

        return *this;
    }

        // Vertex / Vector 
        // Lower case xyzw components
    struct {
        float x, y, z;
        float w;
    };

        // Upper case XYZW components
    struct {
        float X, Y, Z;
        float W;
    };
};

बस अपने निर्माण पैरामीटर पर -msse -msse2 होना न भूलें!


मैं अपने प्रयोगकर्ता से बता सकता हूं कि एसएसई कोड के एक सादे सी संस्करण (कोई इनलाइन एएसएम, कोई अंतर्निहित उपयोग नहीं) पर एक विशाल (4x और ऊपर) गति प्रदान करता है लेकिन हाथ से अनुकूलित असेंबलर कंपाइलर से उत्पन्न असेंबली को हरा सकता है यदि संकलक ' यह पता लगाने के लिए कि प्रोग्रामर का इरादा क्या है (मुझे विश्वास करो, कंपाइलर्स सभी संभावित कोड संयोजनों को कवर नहीं करते हैं और वे कभी नहीं करेंगे)। ओह और, कंपाइलर हर बार डेटा को लेआउट नहीं कर सकता है जो यह सबसे तेज़ गति से चलता है। लेकिन आपको इंटेल-कंपाइलर (यदि संभव हो) पर एक गति के लिए बहुत अधिक प्रयोग करने की आवश्यकता है।


मैं पिछले पोस्टर्स से सहमत हूं। लाभ काफी बड़े हो सकते हैं लेकिन इसे पाने के लिए बहुत सारे काम की आवश्यकता हो सकती है। इन निर्देशों पर इंटेल दस्तावेज़ 4K पृष्ठों से अधिक है। आप ओकेली इंक से मुक्त ईज़ीएसएसई (सी ++ रैपर लाइब्रेरी इंट्रिनिक्स + उदाहरणों पर) देखना चाह सकते हैं।

मुझे लगता है कि इस ईज़ीएसएसई के साथ मेरा संबद्धता स्पष्ट है।


यदि आप एसएसई निर्देशों का उपयोग करते हैं, तो आप स्पष्ट रूप से प्रोसेसर तक सीमित हैं जो इनका समर्थन करते हैं। इसका मतलब x86 है, जो पेंटियम 2 या उससे भी पहले डेटिंग कर रहा है (जब उन्हें पेश किया गया था तब बिल्कुल याद नहीं किया जा सकता है, लेकिन यह बहुत समय पहले है)

एसएसई 2, जो, जहां तक ​​मैं याद कर सकता हूं, वह है जो पूर्णांक संचालन प्रदान करता है, कुछ हद तक हालिया (पेंटियम 3 है? हालांकि पहले एएमडी एथलॉन प्रोसेसर ने उनका समर्थन नहीं किया था)

किसी भी मामले में, आपके पास इन निर्देशों का उपयोग करने के लिए दो विकल्प हैं। या तो असेंबली में कोड का पूरा ब्लॉक लिखें (शायद एक बुरा विचार। यह आपके कोड को अनुकूलित करने के लिए कंपाइलर के लिए लगभग असंभव बनाता है, और मानव के लिए कुशल असेंबलर लिखना बहुत मुश्किल है)।

वैकल्पिक रूप से, अपने कंपाइलर के साथ उपलब्ध इंट्रिनिक्स का उपयोग करें (यदि स्मृति कार्य करता है, तो आमतौर पर उन्हें xmmintrin.h में परिभाषित किया जाता है)

लेकिन फिर, प्रदर्शन में सुधार नहीं हो सकता है। एसएसई कोड प्रक्रियाओं के डेटा की अतिरिक्त आवश्यकताओं को प्रस्तुत करता है। मुख्य रूप से, यह ध्यान में रखना है कि 128-बिट सीमाओं पर डेटा को गठबंधन किया जाना चाहिए। एक ही रजिस्टर में लोड किए गए मानों के बीच कुछ या कोई निर्भरता भी नहीं होनी चाहिए (एक 128 बिट एसएसई रजिस्टर 4 इंट्स रख सकता है। पहले और दूसरे को एक साथ जोड़ना इष्टतम नहीं है। लेकिन सभी चार इंट्स को संबंधित 4 इंट्स में जोड़ना एक और रजिस्टर तेजी से होगा)

यह लाइब्रेरी का उपयोग करने के लिए मोहक हो सकता है जो सभी निम्न-स्तरीय एसएसई झुकाव को लपेटता है, लेकिन इससे किसी भी संभावित प्रदर्शन लाभ को भी बर्बाद कर दिया जा सकता है।

मुझे नहीं पता कि एसएसई का पूर्णांक ऑपरेशन समर्थन कितना अच्छा है, ताकि यह एक ऐसा कारक भी हो जो प्रदर्शन को सीमित कर सके। एसएसई मुख्य रूप से फ्लोटिंग प्वाइंट ऑपरेशंस को तेज करने पर लक्षित है।


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


सिम, जिसमें से एसएसई एक उदाहरण है, आपको डेटा के कई हिस्सों पर एक ही ऑपरेशन करने की अनुमति देता है। इसलिए, आपको पूर्णांक संचालन के लिए सीधे प्रतिस्थापन के रूप में एसएसई का उपयोग करने का कोई फायदा नहीं होगा, यदि आप एक साथ कई डेटा आइटम्स पर संचालन कर सकते हैं तो आपको केवल फायदे मिलेंगे। इसमें कुछ डेटा मान लोड करना शामिल है जो स्मृति में संगत होते हैं, आवश्यक प्रसंस्करण करते हैं और फिर सरणी में मानों के अगले सेट पर जाते हैं।

समस्या का:

1 यदि कोड पथ संसाधित किए जा रहे डेटा पर निर्भर है, तो सिम लागू करने के लिए बहुत कठिन हो जाता है। उदाहरण के लिए:

a = array [index];
a &= mask;
a >>= shift;
if (a < somevalue)
{
  a += 2;
  array [index] = a;
}
++index;

सिम के रूप में करना आसान नहीं है:

a1 = array [index] a2 = array [index+1] a3 = array [index+2] a4 = array [index+3]
a1 &= mask         a2 &= mask           a3 &= mask           a4 &= mask
a1 >>= shift       a2 >>= shift         a3 >>= shift         a4 >>= shift
if (a1<somevalue)  if (a2<somevalue)    if (a3<somevalue)    if (a4<somevalue)
  // help! can't conditionally perform this on each column, all columns must do the same thing
index += 4

2 यदि डेटा संगत नहीं है तो सिम निर्देशों में डेटा लोड करना बोझिल है

3 कोड प्रोसेसर विशिष्ट है। एसएसई केवल आईए 32 (इंटेल / एएमडी) पर है और सभी आईए 32 सीपीयू समर्थन एसएसई नहीं है।

आपको एल्गोरिदम और डेटा का विश्लेषण करने की आवश्यकता है यह देखने के लिए कि क्या यह एसएसई किया जा सकता है और यह जानने की आवश्यकता है कि एसएसई कैसे काम करता है। इंटेल की वेबसाइट पर बहुत सारे दस्तावेज हैं।


सी / सी ++ के लिए इनलाइन असेंबलर पर नज़र डालें, यहां एक डीडीजे आलेख है । जब तक कि आप 100% निश्चित नहीं हैं, आपका प्रोग्राम एक संगत प्लेटफॉर्म पर चलाएगा, आपको यहां दी गई सिफारिशों का पालन करना चाहिए।


हमने कुछ छवि प्रसंस्करण कोड लागू किए हैं, जो आप वर्णन करते हैं, लेकिन बाइट सरणी पर, एसएसई में। सी कोड की तुलना में गतिशील, इंटेल कंपाइलर के संबंध में, 4 के कारक से अधिक सटीक एल्गोरिदम के आधार पर काफी है। हालांकि, जैसा कि आपने पहले ही उल्लेख किया है कि आपके पास निम्न दोष हैं:

  • पोर्टेबिलिटी। कोड प्रत्येक इंटेल जैसे सीपीयू पर चलाएगा, इसलिए एएमडी भी, लेकिन अन्य सीपीयू पर नहीं। यह हमारे लिए कोई समस्या नहीं है क्योंकि हम लक्ष्य हार्डवेयर को नियंत्रित करते हैं। स्विचिंग कंपाइलर्स और यहां तक ​​कि 64 बिट ओएस तक भी एक समस्या हो सकती है।

  • आपके पास एक सीधी सीखने की वक्र है, लेकिन मैंने पाया कि नए एल्गोरिदम लिखने वाले सिद्धांतों को समझने के बाद यह मुश्किल नहीं है।

  • रख-रखाव। अधिकांश सी या सी ++ प्रोग्रामर को असेंबली / एसएसई का कोई ज्ञान नहीं है।

आपको मेरी सलाह केवल तभी जाना होगा जब आपको वास्तव में प्रदर्शन सुधार की आवश्यकता हो, और आपको इंटेल आईपीपी जैसी लाइब्रेरी में आपकी समस्या के लिए कोई फ़ंक्शन नहीं मिल रहा है, और यदि आप पोर्टेबिलिटी समस्याओं के साथ रह सकते हैं।





sse