2015-05-20 10 views
9

जब मैं एसएसई 3 या एवीएक्स का उपयोग कर सकता हूं, तो एसएसई 2 या एमएमएक्स के रूप में पुराने एसएसई संस्करण उपलब्ध हैं -
या क्या मुझे अभी भी उन्हें अलग से जांचने की आवश्यकता है?क्या पुराने सिम-संस्करण नए उपयोग करते समय उपलब्ध हैं?

+1

एक सामान्य नियम के रूप में, आप शायद एक क्षमता के लिए जाँच करनी चाहिए इससे पहले कि आप इसका इस्तेमाल करते हैं। हालांकि, सीपीयूआईडी निर्देश यह निर्धारित करते हैं कि आपके पास एसएसई 3 या एवीएक्स है या नहीं, यह निर्धारित करेगा कि आपके पास एसएसई 2 या एमएमएक्स है या नहीं। यदि आप उचित चर के लिए उन CPUID निर्देशों के आउटपुट को केवल सहेजते हैं, तो आप एक विशिष्ट निर्देश का उपयोग करना चाहते हैं, जब भी आप एक विशिष्ट निर्देश का उपयोग करना चाहते हैं। –

+0

यह एसओ पर पहले आया है, लेकिन मुझे इस समय डुप्लिकेट नहीं मिल रहा है ... –

+1

इंटेल CPU हमेशा पिछड़े संगत होते हैं। इसलिए अगर यह एक अनुदेश तो सेट का समर्थन करता है यह सब पुराने संस्करणों –

उत्तर

8

सामान्यतः, ये additive रहे हैं लेकिन ध्यान रखें कि इन वर्षों में इंटेल और एएमडी समर्थन के बीच अंतर हैं।

यदि आपके पास AVX है, तो आप एसएसई, एसएसई 2, एसएसई 3, एसएसएसई 3, एसएसई 4.1, और एसएसई 4.2 भी मान सकते हैं। याद रखें कि AVX का उपयोग करने के लिए आपको OSXSAVE CPUID बिट को सत्यापित करने की भी आवश्यकता है यह सुनिश्चित करने के लिए सेट किया गया है कि आप जिस ओएस का उपयोग कर रहे हैं वह वास्तव में AVX रजिस्टरों को सहेजने का समर्थन करता है।

आपको अभी भी दृढ़ता से अपने कोड में उपयोग किए जाने वाले सभी CPUID समर्थन की जांच करनी चाहिए (एवीएक्स, ओएसएक्सएसएवी, एसएसई 4, एसएसई 3, एसएसएसई 3 के लिए जांच कर अपने एवीएक्स कोडपैथ की रक्षा के लिए)।

#include <intrin.h> 

inline bool IsAVXSupported() 
{ 
#if defined(_M_IX86) || defined(_M_X64) 
    int CPUInfo[4] = {-1}; 
    __cpuid(CPUInfo, 0); 

    if (CPUInfo[0] < 1 ) 
     return false; 

    __cpuid(CPUInfo, 1); 

    int ecx = 0x10000000 // AVX 
       | 0x8000000 // OSXSAVE 
       | 0x100000 // SSE 4.2 
       | 0x80000 // SSE 4.1 
       | 0x200 // SSSE3 
       | 0x1; // SSE3 

    if ((CPUInfo[2] & ecx) != ecx) 
     return false; 

    return true; 
#else 
    return false; 
#endif 
} 

SSE और SSE2 सभी 64 देशी करने में सक्षम प्रोसेसर के लिए आवश्यक हैं, ताकि उन सभी कोड के लिए अच्छा आधारभूत मान्यताओं कर रहे हैं। विंडोज 8.0, विंडोज 8.1, और विंडोज 10 को स्पष्ट रूप से x86 आर्किटेक्चर के लिए एसएसई और एसएसई 2 समर्थन की आवश्यकता है ताकि उन निर्देश सेटों को सर्वव्यापी बनाया जा सके। दूसरे शब्दों में, यदि आप एसएसई या एसएसई 2 के लिए चेक विफल करते हैं, तो बस एक घातक त्रुटि के साथ ऐप से बाहर निकलें।

#include <windows.h> 

inline bool IsSSESupported() 
{ 
#if defined(_M_IX86) || defined(_M_X64) 
    return (IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE) != 0 && IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE) != 0); 
#else 
    return false; 
#endif 
} 

-या-

#include <intrin.h> 

inline bool IsSSESupported() 
{ 
#if defined(_M_IX86) || defined(_M_X64) 
    int CPUInfo[4] = {-1}; 
    __cpuid(CPUInfo, 0); 

    if (CPUInfo[0] < 1 ) 
     return false; 

    __cpuid(CPUInfo, 1); 

    int edx = 0x4000000 // SSE2 
       | 0x2000000; // SSE 

    if ((CPUInfo[3] & edx) != edx) 
     return false; 

    return true; 
#else 
    return false; 
#endif 
} 

इसके अलावा, मन में है कि MMX, x87 एफपीयू, और AMD 3DNow! * सक्रिय रूप से अब और ताकि आप उन्हें का उपयोग नहीं किया जाना चाहिए, 64 के लिए सभी बहिष्कृत निर्देश सेट मूल निवासी हैं रखना नए कोड में। अंगूठे का एक अच्छा नियम किसी भी आंतरिक का उपयोग करने से बचने के लिए है जो __m64 देता है या __m64 डेटा प्रकार लेता है।

आप इनमें से कई निर्देश सेट और प्रासंगिक प्रोसेसर समर्थन आवश्यकताओं पर नोट्स के साथ यह DirectXMath blog series देख सकते हैं।

नोट (*) - सभी एएमडी 3 डी अब! PREFETCH और PREFETCHW को छोड़कर निर्देशों को बहिष्कृत किया गया है जिन्हें आगे बढ़ाया गया था। पहली पीढ़ी इंटेल 64 प्रोसेसर इन निर्देशों के लिए समर्थन की कमी थी, लेकिन बाद में उन्हें जोड़ा गया क्योंकि उन्हें कोर एक्स 64 निर्देश सेट का हिस्सा माना जाता है। विंडोज 8.1 और विंडोज 10 एक्स 64 को विशेष रूप से PREFETCHW की आवश्यकता है, हालांकि परीक्षण थोड़ा अजीब है। ब्रॉडवेल से पहले अधिकांश इंटेल CPUs वास्तव में PREFETCHW के लिए CPUID के माध्यम से समर्थन रिपोर्ट नहीं करते हैं, लेकिन वे 'अवैध निर्देश' अपवाद को फेंकने के बजाय ऑपोड को नो-ऑप के रूप में देखते हैं। इस प्रकार, यहां परीक्षण है (ए) क्या यह CPUID द्वारा समर्थित है, और (बी) यदि नहीं, तो PREFETCHW कम से कम अपवाद फेंक नहीं देता है।

यहां विजुअल स्टूडियो के लिए कुछ टेस्ट कोड है जो PREFETCHW परीक्षण के साथ-साथ x86 और x64 प्लेटफ़ॉर्म के लिए कई अन्य CPUID बिट्स प्रदर्शित करता है।

#include <intrin.h> 
#include <stdio.h> 
#include <windows.h> 
#include <excpt.h> 

void main() 
{ 
    unsigned int x = _mm_getcsr(); 
    printf("%08X\n", x); 

    bool prefetchw = false; 

    // See http://msdn.microsoft.com/en-us/library/hskdteyh.aspx 
    int CPUInfo[4] = {-1}; 
    __cpuid(CPUInfo, 0); 

    if (CPUInfo[0] > 0) 
    { 
     __cpuid(CPUInfo, 1); 

     // EAX 
     { 
      int stepping = (CPUInfo[0] & 0xf); 
      int basemodel = (CPUInfo[0] >> 4) & 0xf; 
      int basefamily = (CPUInfo[0] >> 8) & 0xf; 
      int xmodel = (CPUInfo[0] >> 16) & 0xf; 
      int xfamily = (CPUInfo[0] >> 20) & 0xff; 

      int family = basefamily + xfamily; 
      int model = (xmodel << 4) | basemodel; 

      printf("Family %02X, Model %02X, Stepping %u\n", family, model, stepping); 
     } 

     // ECX 
     if (CPUInfo[2] & 0x20000000) // bit 29 
      printf("F16C\n"); 

     if (CPUInfo[2] & 0x10000000) // bit 28 
      printf("AVX\n"); 

     if (CPUInfo[2] & 0x8000000) // bit 27 
      printf("OSXSAVE\n"); 

     if (CPUInfo[2] & 0x400000) // bit 22 
      printf("MOVBE\n"); 

     if (CPUInfo[2] & 0x100000) // bit 20 
      printf("SSE4.2\n"); 

     if (CPUInfo[2] & 0x80000) // bit 19 
      printf("SSE4.1\n"); 

     if (CPUInfo[2] & 0x2000) // bit 13 
      printf("CMPXCHANG16B\n"); 

     if (CPUInfo[2] & 0x1000) // bit 12 
      printf("FMA3\n"); 

     if (CPUInfo[2] & 0x200) // bit 9 
      printf("SSSE3\n"); 

     if (CPUInfo[2] & 0x1) // bit 0 
      printf("SSE3\n"); 

     // EDX 
     if (CPUInfo[3] & 0x4000000) // bit 26 
      printf("SSE2\n"); 

     if (CPUInfo[3] & 0x2000000) // bit 25 
      printf("SSE\n"); 

     if (CPUInfo[3] & 0x800000) // bit 23 
      printf("MMX\n"); 
    } 
    else 
     printf("CPU doesn't support Feature Identifiers\n"); 

    if (CPUInfo[0] >= 7) 
    { 
     __cpuidex(CPUInfo, 7, 0); 

     // EBX 
     if (CPUInfo[1] & 0x100) // bit 8 
     printf("BMI2\n"); 

     if (CPUInfo[1] & 0x20) // bit 5 
     printf("AVX2\n"); 

     if (CPUInfo[1] & 0x8) // bit 3 
     printf("BMI\n"); 
    } 
    else 
     printf("CPU doesn't support Structured Extended Feature Flags\n"); 

    // Extended features 
    __cpuid(CPUInfo, 0x80000000); 

    if (CPUInfo[0] > 0x80000000) 
    { 
     __cpuid(CPUInfo, 0x80000001); 

     // ECX 
     if (CPUInfo[2] & 0x10000) // bit 16 
      printf("FMA4\n"); 

     if (CPUInfo[2] & 0x800) // bit 11 
      printf("XOP\n"); 

     if (CPUInfo[2] & 0x100) // bit 8 
     { 
      printf("PREFETCHW\n"); 
      prefetchw = true; 
     } 

     if (CPUInfo[2] & 0x80) // bit 7 
      printf("Misalign SSE\n"); 

     if (CPUInfo[2] & 0x40) // bit 6 
      printf("SSE4A\n"); 

     if (CPUInfo[2] & 0x1) // bit 0 
      printf("LAHF/SAHF\n"); 

     // EDX 
     if (CPUInfo[3] & 0x80000000) // bit 31 
      printf("3DNow!\n"); 

     if (CPUInfo[3] & 0x40000000) // bit 30 
      printf("3DNowExt!\n"); 

     if (CPUInfo[3] & 0x20000000) // bit 29 
      printf("x64\n"); 

     if (CPUInfo[3] & 0x100000) // bit 20 
      printf("NX\n"); 
    } 
    else 
     printf("CPU doesn't support Extended Feature Identifiers\n"); 

    if (!prefetchw) 
    { 
     bool illegal = false; 

     __try 
     { 
      static const unsigned int s_data = 0xabcd0123; 

      _m_prefetchw(&s_data); 
     } 
     __except (EXCEPTION_EXECUTE_HANDLER) 
     { 
      illegal = true; 
     } 

     if (illegal) 
     { 
      printf("PREFETCHW is an invalid instruction on this processor\n"); 
     } 
    } 
} 

अद्यतन: मौलिक चुनौती, निश्चित रूप से, आप कैसे प्रणाली है कि AVX लिए समर्थन की कमी संभाल करते है? जबकि निर्देश सेट उपयोगी है, एवीएक्स-सक्षम प्रोसेसर रखने का सबसे बड़ा लाभ /arch:AVX बिल्ड स्विच का उपयोग करने की क्षमता है जो बेहतर एसएसई/एसएसई 2 कोड-जेन के लिए VEX prefix के वैश्विक उपयोग को सक्षम बनाता है। एकमात्र समस्या परिणामस्वरूप कोड डीएलएल/एक्सई उन प्रणालियों के अनुकूल नहीं है जिनमें AVX समर्थन की कमी है।

इस तरह, विंडोज के लिए, आदर्श रूप से आपको गैर-एवीएक्स सिस्टम के लिए एक EXE बनाना चाहिए (एसएसई/एसएसई 2 मानते हैं, इसलिए x86 कोड के लिए /arch:SSE2 का उपयोग करें; यह सेटिंग x64 कोड के लिए निहित है), एक अलग EXE जिसे अनुकूलित किया गया है AVX के लिए (/arch:AVX का उपयोग करके), और उसके बाद यह निर्धारित करने के लिए कि कौन सी EXE किसी दिए गए सिस्टम के लिए उपयोग करने के लिए CPU पहचान का उपयोग करें।

Xbox वन के साथ सौभाग्य से, हम सिर्फ हमेशा /arch::AVX साथ निर्माण कर सकते हैं के बाद से यह एक निश्चित मंच है ...

+0

मैं इसे एक अच्छा विचार है विभिन्न निर्देश सेट के लिए अलग से निष्पादन योग्य बनाने के लिए नहीं लगता है । एक [सीपीयू डिस्पैचर] (https://stackoverflow.com/questions/23676426/disable-avx2-functions-on-non-haswell-processors/23677889#23677889) का उपयोग कर एक निष्पादन मेरी राय में अधिक आदर्श है। –

+0

''/arch: AVX'' स्विच एक संपूर्ण मॉड्यूल पर लागू होता है, केवल एक फ़ंक्शन नहीं, लेकिन हां सिद्धांत में आप प्रत्येक फ़ंक्शन के लिए अलग-अलग सीपीपी फाइलें बना सकते हैं और विभिन्न बिल्ड सेटिंग्स के साथ संकलित कर सकते हैं। –

+0

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

4

एक सामान्य नियम के रूप में - SSE/AVX की अलग-अलग पीढ़ियों मिश्रित नहीं होते हैं जब तक आप के लिए है। यदि आप करते हैं, सुनिश्चित करें कि आप vzeroupper या इसी तरह राज्य समाशोधन निर्देशों का उपयोग करें, अन्यथा आप आंशिक मूल्यों खींचें और अनजाने में झूठी निर्भरता बना सकते हैं, के बाद से रजिस्टरों की सबसे मोड के बीच भी साझा कर रहे हैं जब समाशोधन, मोड के बीच स्विच, दंड का कारण हो सकता आधार पर कर सटीक सूक्ष्म वास्तुकला पर।

अतिरिक्त पठन - आपको क्या करना चाहिए पर अच्छी सलाह के लिए https://software.intel.com/sites/default/files/m/d/4/1/d/8/11MC12_Avoiding_2BAVX-SSE_2BTransition_2BPenalties_2Brh_2Bfinal.pdf

+0

निष्पक्ष बनाने के लिए इस मिश्रण समस्या केवल तब होता है जब आप गैर VEX मिश्रण कोड का उपयोग कर VEX के साथ कोड (यानी, पहले 2 ऑपरेंड एसएसई निर्देशों के साथ AVX या AVX2 मिश्रण)। इसके अलावा पीढ़ियों के बीच मिश्रण करना ठीक और आवश्यक है - आवश्यक है क्योंकि प्रत्येक एक्सटेंशन स्वयं एक पूर्ण उपयोगी यूएसए नहीं है बल्कि अंतिम पर बनाता है। – BeeOnRope

+0

@BeeOnRope, मिश्रण करना ठीक है, लेकिन आपको उस मुद्दे से खुद को बचाने की ज़रूरत है जिसके बारे में मैं बात कर रहा था। देखें - http: // stackoverflow।कॉम/प्रश्न/7839 9 25/उपयोग-एवीएक्स-सीपीयू-निर्देश-खराब-प्रदर्शन-बिना-archavx – Leeor

+0

हाँ बिल्कुल, लेकिन यह सवाल थोड़ा अस्पष्ट है क्योंकि यह इंगित नहीं करता है कि लगभग सभी दिलचस्प एसएसई निर्देशों में एक VEX- एन्कोडेड संस्करण - 128-बिट संस्करणों सहित। बहुत से लोग अभी भी उन "एसएसई" निर्देशों को बुलाते हैं। उदाहरण के लिए, आप सुनेंगे कि 'pshufb' एक' एसएसई 3 'निर्देश है। वास्तव में 'phsufb xmm0, xmm1' जैसे एक आमंत्रण एक गैर-वेक्स एन्कोडिंग बनाता है जो आपके द्वारा उल्लेख की जाने वाली प्रदर्शन समस्या का कारण बनता है। बस इसे समान रूप से व्यवहार किए गए 'pshufb xmm0, xmm0, xmm1' में बदलना, हालांकि, इसे VEX-एन्कोडिंग में बदलता है और समस्या से बचाता है। – BeeOnRope

3

चक के देखें जवाब। यदि आप उत्सुक हैं, तो पूछे गए प्रश्न के शाब्दिक उत्तर के लिए यह उत्तर देखें।


AVX समर्थन बिल्कुल सब इंटेल SSE * निर्देश सेट के लिए समर्थन की गारंटी देता है, क्योंकि यह उन सभी की VEX एन्कोड संस्करण भी शामिल है। चूंकि चक बताते हैं, आप अपने कोड को ब्लूएट किए बिना, बिटमैस्क के साथ एक ही समय में पिछले लोगों की जांच कर सकते हैं, लेकिन इसे पसीना न पड़े।

ध्यान दें कि POPCNT, TZCNT, और सामान की तरह SSE-कुछ भी का हिस्सा नहीं हैं। POPCNT की अपनी विशेषता है। LZCNT की अपनी विशेषता बिट भी है, क्योंकि एएमडी ने इसे बीएमआई 1 से अलग से पेश किया है। TZCNT हालांकि बीएमआई 1 का हिस्सा है। के बाद से कुछ BMI1 निर्देश VEX एन्कोडिंग का उपयोग, यहां तक ​​कि नवीनतम पीढ़ी पेंटियम/सेलेरोन सीपीयू (Skylake पेंटियम की तरह) BMI1 जरूरत नहीं है। :(मैं इंटेल बस छोड़ AVX/AVX2 चाहता था लगता है, शायद इसलिए वे पेन्टियम के रूप में निष्पादन इकाइयों की दोषपूर्ण ऊपरी गलियों के साथ सीपीयू बेचने सकता है, और वे डिकोडर में VEX समर्थन को अक्षम करके यह करते हैं।


इंटेल एसएसई समर्थन अब तक जारी किए गए सभी सीपीयू में वृद्धिशील रहा है। एसएसई 4.1 एसएसएसई 3, एसएसई 3, एसएसई 2, और एसएसई का तात्पर्य है। और एसएसई 4.2 पिछले सभी का तात्पर्य है। मुझे यकीन नहीं है कि क्या कोई आधिकारिक x86 दस्तावेज किसी की संभावना को रोकता है लेकिन SSE4.1 समर्थन के साथ सीपीयू नहीं SSSE3। (यानी बाहर छोड़ PSHUFB, जो संभवतः महंगा करने के लिए लागू करते हैं। है) यह, हालांकि, व्यवहार में अत्यंत संभावना नहीं है के बाद से इस में कई लोगों की मान्यताओं का उल्लंघन होगा। जैसा कि मैंने कहा, यह भी हो सकता है आधिकारिक तौर पर मना किया है, लेकिन मैं ध्यान से जांच नहीं की।


AVX एएमडी SSE4a या AMD XOP शामिल नहीं है। विशेष रूप से एएमडी एक्सटेंशन की जांच की जानी चाहिए। यह भी ध्यान रखें कि नवीनतम एएमडी सीपीयू एक्सओपी समर्थन छोड़ रहे हैं। (इंटेल ने इसे कभी नहीं अपनाया, इसलिए ज्यादातर लोग इसका लाभ लेने के लिए कोड नहीं लिखते हैं, इसलिए एएमडी के लिए उन ट्रांजिस्टर ज्यादातर बर्बाद हो जाते हैं। इसमें 2-स्रोत बाइट परमिट की तरह कुछ अच्छी चीजें होती हैं, जिससे बाइट एलयूटी दो बार एवीएक्स 2 के वीपीएसएचयूएफबी यम की इन-लेन सीमा के बिना पीएसएचयूएफबी के रूप में चौड़ा)।


SSE2 x86-64 वास्तुकला के लिए आधारभूत है। आपको 64-बिट बिल्डों में एसएसई या एसएसई 2 समर्थन की जांच करने की आवश्यकता नहीं है। मैं भूल जाता हूं कि एमएमएक्स बेसलाइन भी है। लगभग निश्चित रूप से।

SSE अनुदेश सेट कुछ निर्देश है कि MMX रजिस्टर पर काम भी शामिल है। (उदाहरण के लिए PMAXSW mm1, mm2/m64 एसएसई के साथ नया था। एक्सएमएम संस्करण एसएसई 2 का हिस्सा है।) 32-बिट सीपीयू का समर्थन करने वाले एसएसई को एमएमएक्स रजिस्टरों की आवश्यकता होती है। एमएमएक्स रजिस्ट्रार रखने के लिए पागलपन होगा लेकिन केवल उन एसएसई निर्देशों का समर्थन करेगा जो मूल एमएमएक्स निर्देशों (उदाहरण के लिए movq mm0, [mem]) का उपयोग करते हैं। हालांकि, मुझे कुछ निश्चित नहीं मिला है जो एसएसई के साथ x86- आधारित Deathstation 9000 की संभावना से बाहर है लेकिन एमएमएक्स सीपीयूआईडी फीचर बिट्स नहीं है, लेकिन मैं इंटेल के आधिकारिक x86 मैनुअल में नहीं आया। (लिंक के लिए टैग विकी देखें)।

MMX वैसे भी उपयोग न करें, यह आम तौर पर धीमी भले ही आप केवल, पर काम करने के लिए एक XMM रजिस्टर के कम आधे में एक समय में 64 बिट्स है है। नवीनतम सीपीयू (जैसे इंटेल स्काइलेक) में एक्सएमएम संस्करण की तुलना में कुछ निर्देशों के एमएमएक्स संस्करणों के लिए कम थ्रूपुट है। कुछ मामलों में, इससे भी बदतर विलंबता। उदाहरण के लिए, Agner Fog's testing के अनुसार, PACKSSWB mm0, mm1 स्किलेक पर 2 सी विलंबता के साथ 3 यूओप्स है। 128 बी और 256 बी एक्सएमएम/वाईएमएम संस्करण 1 यू विलंबता के साथ 1 यूओपी हैं।

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

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