2011-04-14 24 views
7

मैंने अक्सर पढ़ा है कि यह एक पर्फ परिप्रेक्ष्य से बुरा है कि शाखाकरण, एक असेंबली निर्देश स्तर पर, बुरा है। लेकिन मैंने वास्तव में नहीं देखा है कि ऐसा क्यों है। तो क्यों?जहां संभव हो वहां निर्देश शाखा से बचने के लिए अच्छा क्यों है?

उत्तर

12

अधिकांश आधुनिक प्रोसेसर prefetch निर्देश और यहां तक ​​कि speculatively execute कोड प्रवाह उस निर्देश तक पहुंचने से पहले भी हैं। शाखा होने का मतलब है कि अचानक दो अलग-अलग निर्देश हैं जो अगले निर्देश हो सकते हैं। कम से कम तीन संभावित तरीकों से यह पूर्व-fetching के साथ बातचीत कर सकते हैं:

  • शाखाओं के बाद निर्देश पूर्व-प्राप्त नहीं किए जाते हैं। instruction pipeline खाली हो जाता है और प्रोसेसर को प्रतीक्षा करना चाहिए क्योंकि अगले निर्देश को अंतिम पल में लाया जाता है, जिससे खराब प्रदर्शन होता है।
  • प्रोसेसर अनुमान कौन सी शाखा ली जाएगी (branch prediction) और उचित निर्देश को प्रीफ़ेच और निष्पादित करें। यदि यह गलत शाखा का अनुमान लगाता है तो उसे किए गए काम को त्यागना होगा, और सही निर्देश प्राप्त करने की प्रतीक्षा करें।
  • प्रोसेसर दोनों शाखाओं को प्राप्त और निष्पादित कर सकता है और उसके बाद किए गए शाखा से परिणामों को त्यागें।

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

कोड के एक विशिष्ट टुकड़े के लिए भविष्यवाणी करना मुश्किल हो सकता है कि शाखा को हटाने से कोड को काफी तेज कर दिया जाएगा। जब माइक्रो-ऑप्टिमाइज़िंग अनुमान लगाने के बजाए दोनों दृष्टिकोणों के प्रदर्शन को मापने के लिए सबसे अच्छा है।

1

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

2

यह खराब है क्योंकि यह instruction prefetch में हस्तक्षेप करता है। आधुनिक प्रोसेसर तेजी से चलाने के लिए पहले प्रोसेस करते समय अगली कमांड के बाइट लोड करना शुरू कर सकते हैं। जब कोई शाखा होती है, तो "अगली कमांड" जिसे प्रीफेच किया गया था उसे फेंक दिया जाना चाहिए, जो समय बर्बाद कर देता है। एक तंग पाश या पसंद के अंदर, उन मिस्ड प्रीफेच जोड़ सकते हैं।

1

प्रीफ़ेच मुद्दों के अलावा, अगर तुम कूद रहे हैं, आप नहीं अन्य काम कर रहे हैं ...

0

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

एक प्रोसेसर में निर्देश पाइपलाइन ठीक उसी तरह काम करता है, पाइपलाइन में सैकड़ों कदम नहीं हैं, लेकिन यह अवधारणा एक ही है, प्रति घड़ी चक्र निष्पादन दर (प्रति कारों की एक्स संख्या) दिन) आपको उस पाइपलाइन को आसानी से चलाना होगा। तो आप prefetch, जो एक स्मृति चक्र जलता है, जो आमतौर पर धीमा है लेकिन कैशिंग की परतें मदद करता है। डीकोड, एक और घड़ी लेता है, निष्पादित करता है, एक सीआईएससी पर एक x86 की तरह कई घड़ियों esp ले सकते हैं। जब आप अधिकांश प्रोसेसर पर शाखा करते हैं, तो आपको सामान्य, सरलीकृत पाइपलाइन के संदर्भ में लगता है कि मूल रूप से आपके पाइपलाइन के 2/3s निष्पादन और प्रीफेच में निर्देश को फेंकना होगा। फिर आपको उन घड़ियों को लाने के लिए इंतजार करना होगा, और चिकनी निष्पादन में वापस आने से पहले डीकोड करना होगा। उस पर, परिभाषा के अनुसार, अगली निर्देश नहीं होने के कारण, समय का कुछ प्रतिशत कैशलाइन से अधिक है और उस समय का कुछ प्रतिशत जिसका अर्थ स्मृति या उच्च परत कैश से मिलता है जो कि और भी घड़ी है यदि आप रैखिक रूप से निष्पादित कर रहे थे तो चक्र। दूसरा आम समाधान यह है कि कुछ प्रोसेसर बताते हैं कि शाखा निर्देश के बाद जो कुछ भी निर्देश है या शाखा निर्देश के बाद कभी-कभी दो निर्देश हमेशा निष्पादित होते हैं। इस तरह आप निष्पादित करते हैं जैसे आप पाइप को फ्लश करते हैं, एक अच्छा कंपाइलर निर्देशों की व्यवस्था करेगा ताकि प्रत्येक शाखा के बाद कुछ अन्य एनओपी हो। आलसी तरीका हालांकि हर शाखा के बाद सिर्फ एक नॉप या दो डालना है, एक और प्रदर्शन हिट बनाना, लेकिन उस प्लेटफ़ॉर्म के लिए अधिकांश लोगों का उपयोग किया जाएगा। एक तीसरा तरीका एआरएम करता है, जिसमें सशर्त निष्पादन होता है। संक्षेप में, आगे की शाखाएं, जो कि असामान्य नहीं हैं, यदि स्थिति हो तो शाखा कहने के बजाय, आप कुछ निर्देशों को चिह्नित करते हैं जिन्हें आप स्थिति के साथ निष्पादित करने के लिए शाखा बनाने की कोशिश कर रहे हैं, वे डीकोड में जाते हैं और निष्पादित करते हैं और नॉप और पाइप के रूप में निष्पादित करते हैं चलती रहती है। एआरएम पारंपरिक फ्लश पर निर्भर करता है और लंबी या पिछड़ी शाखाओं के लिए फिर से भरता है।

पुराने x86 (8088/86) मैनुअल के साथ-साथ अन्य प्रोसेसर के साथ-साथ माइक्रोकंट्रोलर मैनुअल (नए और पुराने) के लिए अन्य समान पुराने प्रोसेसर मैनुअल भी प्रति निर्देश निष्पादन के लिए घड़ी चक्र प्रकाशित करेंगे। और शाखा निर्देशों के लिए यह कहता है कि शाखा होने पर घड़ियों की एक्स संख्या जोड़ें। आपके आधुनिक x86 और यहां तक ​​कि एआरएम और अन्य प्रोसेसर जो विंडोज या लिनक्स या अन्य (भारी और धीमी) ऑपरेटिंग सिस्टम चलाने के इरादे से परेशान नहीं हैं, वे अक्सर कहते हैं कि यह प्रति घड़ी एक निर्देश चलाता है या मेगाहर्ट्ज या ऐसी चीजों को मिप्स के बारे में बात करता है और जरूरी नहीं है प्रति निर्देश घड़ियों की एक मेज है। आप बस एक मानते हैं, और याद रखें कि प्रति दिन एक कार की तरह है, यह आखिरी निष्पादन घड़ी अन्य घड़ियों को वहां नहीं लेती है। माइक्रोकंट्रोलर लोग विशेष रूप से एक घड़ी प्रति निर्देश के साथ सौदा करते हैं, और औसत डेस्कटॉप एप्लिकेशन की तुलना में निष्पादन के समय के बारे में अधिक जागरूक होना चाहिए। उनमें से कुछ के लिए चश्मा देखें माइक्रोचिप पीआईसी (पीआईसी 32 नहीं, जो कि एमआईपीएस है), एमएसपी 430, निश्चित रूप से 8051, हालांकि वे कई अलग-अलग कंपनियों द्वारा बनाए गए हैं या उनके समय के चश्मे जंगली रूप से भिन्न होते हैं।

डेस्कटॉप अनुप्रयोगों या यहां तक ​​कि एक ऑपरेटिंग सिस्टम पर कर्नेल ड्राइवरों के लिए नीचे की रेखा, कंपाइलर इतना कुशल नहीं है और ऑपरेटिंग सिस्टम इतना अधिक ओवरहेड जोड़ता है कि आपको घड़ी की बचत शायद ही कभी दिखाई देगी। एक माइक्रोकंट्रोलर पर स्विच करें और इसमें बहुत सी शाखाएं डालें और आपका कोड 2 या 3 गुना धीमा हो। एक कंपाइलर के साथ भी और असेंबलर नहीं। एक कंपाइलर (असेंबलर में लिखना नहीं) का उपयोग करके अनुमोदित किया जा सकता है/आपके कोड को 2 से 3 गुना धीमा कर देगा, आपको प्रदर्शन के साथ विकास, रखरखाव और पोर्टेबिलिटी को संतुलित करना होगा।

+0

उत्कृष्ट सारांश! –