अगर बनाम स्विच स्पीड


112

कंपाइल ऑप्टिमाइजेशन के कारण स्विच स्टेटमेंट आमतौर पर इफ-इफ-इफ स्टेटमेंट (जैसे कि इस लेख में descibed ) के बराबर होता है ।

यह अनुकूलन वास्तव में कैसे काम करता है? किसी को भी एक अच्छी व्याख्या है?



एक संभावित अच्छा उत्तर: dotnetperls.com/if-switch-performance
बाबाक

जवाबों:


185

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

यह जंजीर ifपरीक्षण के बहुत से स्पर्शोन्मुख बेहतर रनटाइम है और वास्तव में अपेक्षाकृत कुछ तारों के लिए भी तेज है।


6
अच्छा जवाब, हैश टेबल के बारे में दिलचस्प।
बॉबीशैफ्टो

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

इसका मतलब है: स्विच (ए) केस "एक्स": केस "वाई": केस "जेड": // कुछ ब्रेक; } इससे अधिक तेज़ है: अगर (a == "x" || a == "b" || = a == "c") // कुछ सही है?
yazanpro 21

यहाँ हमें कोई और नहीं घोंसला है, केवल या तो आप क्या सोचते हैं?
yazanpro 21

@yazanpro पुराने संकलक पर संभावित रूप से हाँ (लेकिन ध्यान दें कि मामलों की संख्या इतनी कम है कि इससे कोई फर्क नहीं पड़ सकता है!)। आधुनिक कंपाइलर हालांकि बहुत अधिक कोड विश्लेषण करते हैं। परिणामस्वरूप, वे यह पता लगा सकते हैं कि ये दो कोड स्निपेट समान हैं, और समान अनुकूलन लागू करते हैं। लेकिन यह मेरी ओर से शुद्ध अटकलें हैं, मुझे नहीं पता कि कोई संकलक वास्तव में ऐसा करता है या नहीं।
कोनराड रुडोल्फ

15

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

किसी भी तरह, कोनराड के जवाब का एक विस्तार यह है कि संकलक एक कूद तालिका उत्पन्न कर सकता है, लेकिन यह जरूरी नहीं कि गारंटी है (न ही वांछनीय)। विभिन्न कारणों से जंप टेबल आधुनिक प्रोसेसर पर शाखा के भविष्यवक्ताओं के लिए बुरा काम करते हैं, और टेबल स्वयं कैश व्यवहार, जैसे कि बुरा काम करते हैं।

switch(a) { case 0: ...; break; case 1: ...; break; }

यदि एक संकलक ने वास्तव में इसके लिए एक कूद तालिका बनाई है, तो यह संभवतः धीमी हो जाएगी कि if..else if..कूद तालिका को पराजित करने के कारण वैकल्पिक शैली कोड।


4

बिना मैच के आँकड़े अच्छे नहीं हो सकते।

यदि आप वास्तव में स्रोत को डाउनलोड करते हैं, तो कोई भी मैच वैल्यू 21 में नहीं जानी जाती है, अगर और स्विच केस दोनों में। एक संकलक को दूर करने में सक्षम होना चाहिए, यह जानकर कि हर समय किस कथन को चलाया जाना चाहिए, और सीपीयू को ठीक से भविष्यवाणी करने में सक्षम होना चाहिए।

अधिक दिलचस्प मामला यह है कि जब मेरी राय में हर मामला नहीं टूटता है, लेकिन यह प्रयोग का दायरा नहीं हो सकता है।


4

स्विच / केस स्टेटमेंट आम तौर पर 1-स्तरीय गहरे हो सकते हैं, लेकिन जब आप 2 या अधिक में मिलना शुरू करते हैं, तो स्विच / केस स्टेटमेंट तब तक 2-3 बार लेना शुरू कर देते हैं जब तक कि नेस्टेड हो / नहीं तो स्टेटमेंट।

इस लेख में कुछ गति तुलनाओं को उजागर किया गया है, जब ऐसे बयानों को नेस्टेड किया जाता है।

उदाहरण के लिए, उनके परीक्षणों के अनुसार, निम्न की तरह नमूना कोड:

if (x % 3 == 0)
            if (y % 3 == 0)
                total += 3;
            else if (y % 3 == 1)
                total += 2;
            else if (y % 3 == 2)
                total += 1;
            else
                total += 0;
        else if (x % 3 == 1)
            if (y % 3 == 0)
                total += 3;
            else if (y % 3 == 1)
                total += 2;
            else if (y % 3 == 2)
                total += 1;
            else
                total += 0;
        else if (x % 3 == 2)
            if (y % 3 == 0)
                total += 3;
            else if (y % 3 == 1)
                total += 2;
            else if (y % 3 == 2)
                total += 1;
            else
                total += 0;
        else
            if (y % 3 == 0)
                total += 3;
            else if (y % 3 == 1)
                total += 2;
            else if (y % 3 == 2)
                total += 1;
            else
                total += 0;

आधे समय में समाप्त हो गया समतुल्य स्विच / केस स्टेटमेंट चलाने के लिए:

switch (x % 3)
    {
        case 0:
            switch (y % 3)
            {
                case 0: total += 3;
                    break;
                case 1: total += 2;
                    break;
                case 2: total += 1;
                    break;
                default: total += 0;
                    break;
            }
            break;
        case 1:
            switch (y % 3)
            {
                case 0: total += 3;
                    break;
                case 1: total += 2;
                    break;
                case 2: total += 1;
                    break;
                default: total += 0;
                    break;
            }
            break;
    case 2:
            switch (y % 3)
            {
                case 0: total += 3;
                    break;
                case 1: total += 2;
                    break;
                case 2: total += 1;
                    break;
                default: total += 0;
                    break;
            }
            break;
    default:
        switch (y % 3)
        {
            case 0: total += 3;
                break;
            case 1: total += 2;
                break;
            case 2: total += 1;
                break;
            default: total += 0;
                break;
        }
        break;
    }

हाँ, यह एक अल्पविकसित उदाहरण है, लेकिन यह इस बिंदु को दिखाता है।

तो एक निष्कर्ष सरल प्रकारों के लिए स्विच / केस का उपयोग हो सकता है जो केवल एक स्तर गहरे हैं, लेकिन अधिक जटिल तुलनाओं और कई नेस्टेड स्तरों के लिए क्लासिक का उपयोग करते हैं यदि / अन्यथा निर्माण करते हैं?


-1: 1. लेख ने शाखा भविष्यवाणी को पूरी तरह से नजरअंदाज कर दिया, 2. एल्गोरिदम बिल्कुल समान नहीं हैं (लिंक पर एकल-अगर एक पहले से ही अधिक अनुकूलित कोडित है) और 3. पाया गया अंतर इतना छोटा है कि कुछ भी बहाना नहीं है उचित, स्वच्छ कोड का उपयोग (10.000.000 में 4 ns के बीच स्विच और इसी तरह और निर्माण के बीच)
ट्रोजनर

स्विच ब्लॉक में कितने मामलों के कारण यह उदाहरण अनुकूलित नहीं होगा। आमतौर पर 5-6 तत्वों के बाद यह एक जंप टेबल उत्पन्न करेगा।
antiduh

0

यदि ओवर केस का एकमात्र लाभ यह है कि पहले मामले की घटना आवृत्ति की ध्यान देने योग्य वृद्धि होती है।

निश्चित रूप से यह सुनिश्चित नहीं है कि सीमा कहां है, लेकिन मैं केस सिंटैक्स का उपयोग करता हूं जब तक कि पहले "लगभग हमेशा" पहला परीक्षण पास न करें।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.