29

चूंकि मैंने प्रोग्रामिंग शुरू की है, इसलिए मैंने हर जगह बेकार शाखाओं से बचने के लिए हर जगह पढ़ा है।सीपीयू शाखा निर्देश क्यों धीमा है?

यह ठीक है, हालांकि किसी भी लेख ने समझाया कि मुझे ऐसा क्यों करना चाहिए। क्या होता है जब CPU शाखा निर्देश डीकोड करता है और कूदने का फैसला करता है? और "चीज" क्या है जो इसे अन्य निर्देशों (जैसे अतिरिक्त) से धीमी बनाती है?

उत्तर

41

एक शाखा निर्देश किसी भी अन्य निर्देश की तुलना में स्वाभाविक रूप से धीमी नहीं है।

हालांकि, आपने सुना है कि शाखाओं से बचा जाना चाहिए क्योंकि आधुनिक CPUs pipeline architecture का पालन करते हैं। इसका मतलब है कि कई अनुक्रमिक निर्देश एक साथ निष्पादित किए जा रहे हैं। लेकिन पाइपलाइन का केवल पूरी तरह से उपयोग किया जा सकता है यदि यह प्रत्येक चक्र पर स्मृति से अगले निर्देश को पढ़ने में सक्षम है, जिसका अर्थ है कि इसे पढ़ने के लिए निर्देश जानने की आवश्यकता है।

सशर्त शाखा पर, यह आमतौर पर समय से पहले नहीं जानता कि कौन सा रास्ता लिया जाएगा। तो जब ऐसा होता है, तो सीपीयू को तब तक रोकना पड़ता है जब तक कि निर्णय का समाधान नहीं हो जाता है, और शाखा निर्देश के पीछे पाइपलाइन में सब कुछ फेंकता है। यह उपयोग कम करता है, और इसलिए प्रदर्शन।

यही कारण है कि branch prediction और branch delay slots जैसी चीजें मौजूद हैं।

+7

+1: इस मुद्दे के लिए भी महत्वपूर्ण: आधुनिक CPUs में आमतौर पर [बर्न भविष्यवाणियों] (http://en.wikipedia.org/wiki/Branch_predictor) को इस पे को कम करने के लिए महत्वपूर्ण है सुधार नुकसान। – amit

+0

लेकिन ऐसी तकनीकें हैं जो "शाखा भविष्यवाणी" (http://en.wikipedia.org/wiki/Branch_prediction) नामक इस प्रक्रिया को तेज करती हैं। यह हमेशा काम नहीं करता है लेकिन सामान्य रूप से यह बेहतर काम करता है। संपादित करें: मैं बहुत धीमी हूँ। xD – alfa

+0

बस इसे स्पष्ट करने के लिए: पाइपलाइन को रोकने का मतलब है कि प्रीलोड किए गए सभी निर्देशों को अनलोड किया जाना चाहिए। इसके अलावा, किसी भी संभावित दुष्प्रभाव को वापस लेना चाहिए (आमतौर पर डेटा जो गलत तरीके से शाखा के कारण बदल गया है)। इन सभी परिचालनों में समय और ऊर्जा खर्च होती है। – NeXuS

6

क्योंकि सीपीयू निर्देशों को निष्पादित करने के लिए पाइपलाइन को गोद लेता है, जिसका अर्थ है कि जब किसी चरण में पिछले निर्देश को निष्पादित किया जा रहा है (उदाहरण के लिए, रजिस्टरों से मूल्य पढ़ना), तो अगला निर्देश एक ही समय में निष्पादित हो जाएगा, लेकिन एक और चरण में (उदाहरण के लिए, डीकोडिंग चरण)। यह गैर-नियंत्रण निर्देशों के लिए ठीक है, लेकिन यह चीज जटिल बनाता है जब नियंत्रण निर्देश jmp या call निष्पादित किए जाते हैं।

चूंकि सीपीयू क्या अगले निर्देश जब एक jmp अनुदेश क्रियान्वित हो जाएगा पता नहीं है, यह branch prediction तकनीकों का उपयोग करता भविष्यवाणी करने के लिए कि क्या शाखा अनुदेश या नहीं लिया जाएगा (उदाहरण के लिए, एक पाश स्निपेट में एक शाखा अनुदेश शायद ले जाएगा लूप हेड पर निर्देश प्रवाह वापस)।

हालांकि, जब ऐसी भविष्यवाणी विफल हो जाती है, जिसे branch misprediction कहा जाता है, तो यह निष्पादन प्रदर्शन को प्रभावित करेगा। चूंकि शाखा के बाद पाइपलाइन को त्यागना पड़ता है, और सही निर्देश से शुरू होता है।

3

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

आप माइक्रोसॉफ्ट कंपाइलर here में सी ++ अनुकूलन के बारे में और अधिक पढ़ सकते हैं - प्रोफ़ाइल मार्गदर्शित ऑप्टिमाइज़र आपके कोड को अनुकूलित करने के लिए रनटाइम जानकारी का उपयोग करता है (यानी कोड के कौन से हिस्से सबसे अधिक उपयोग किए जाते हैं)। स्पीड-अप 20% रेंज में है।

संचालन में से एक "सशर्त शाखा अनुकूलन", उदाहरण के लिए है - समय की सबसे यह सोचते हैं मैं 6 - इस तेजी से होता है:

if (i==6) 
{ 
    //... 
} 

else 
{ 
    switch (i) 
    { 
     case 1: // 
     case 2: // 
     //... 
    } 
} 

से:

switch (i) 
{ 
    case 1: // 
    //... 
    case 6: // 
    case 7: // 
} 

यहाँ एक है अन्य अनुकूलन पर ब्लॉग पोस्ट: http://bogdangavril.wordpress.com/2011/11/02/optimizating-your-native-program/

+0

बहुत उपयोगी लेख! मैं पहले से ही अपने कोड में बिट्स देख सकता हूं जिसे बेहतर किया जा सकता है! – user1010005