2013-02-17 12 views
7

मैं कॉर्टेक्स-एम आधारित microcontroller पर -127 और 127 के बीच एक मूल्य को क्लैंप करने का प्रयास कर रहा हूं।सी क्या यह शाखा रहित हैक वास्तव में तेज़ है?

मेरे पास दो प्रतिस्पर्धी कार्य हैं, एक सशर्त उपयोग करता है, दूसरा एक शाखा रहित हैक का उपयोग करता है जिसे मैंने here पाया।

// Using conditional statements 
int clamp(int val) { return ((val > 127) ? 127 : (val < -127) ? -127 : val); } 

// Using branchless hacks 
int clamp(int val) { 
    val -= -127; 
    val &= (~val) >> 31; 
    val += -127; 
    val -= 127; 
    val &= val >> 31; 
    val += 127; 

    return val; 
} 

अब मैं कुछ मामलों इन तरीकों में से एक अन्य की तुलना में तेजी से हो सकता में जानते हैं, और शिकंजा प्रतिकूल लेकिन सामान्य रूप में इसके लायक है यह रूप में यह वास्तव में मेरे लिए कोई फर्क नहीं पड़ता देखकर शाखा तकनीक का उपयोग करने के लिए जो मैं उपयोग करता हूं, वे दोनों मेरे मामले में ठीक काम करेंगे?

माइक्रोकंट्रोलर पर एक छोटी सी पृष्ठभूमि, यह एक एआरएम आधारित माइक्रोकंट्रोलर है जो 3 एमआईपीएस पर 3 चरण पाइपलाइन, fetch, decode और execute के साथ चल रहा है और ऐसा लगता है कि कुछ प्रकार की शाखा भविष्यवाणी है लेकिन मैं विवरण खोद नहीं पा रहा था।

+10

क्या आपने इसे बेंचमार्क किया था? –

+3

ऐसा लगता है कि कोड संकलित होने पर ऑप्टिमाइज़ेशन बंद थे। –

+8

आप एआरएम पर प्रदर्शन के बारे में परवाह करते हैं, लेकिन आप x86 के लिए जेनरेट एएसएम देख रहे हैं। यह आपको कहीं भी नहीं जा रहा है। – hobbs

उत्तर

4

एआरएम कोड (-O3 साथ जीसीसी 4.6.3):

clamp1: 
    mvn r3, #126 
    cmp r0, r3 
    movlt r0, r3 
    cmp r0, #127 
    movge r0, #127 
    bx lr 

clamp2: 
    add r0, r0, #127 
    mvn r3, r0 
    and r0, r0, r3, asr #31 
    sub r0, r0, #254 
    and r0, r0, r0, asr #31 
    add r0, r0, #127 
    bx lr 

अँगूठा कोड:

clamp1: 
    mvn r3, #126 
    cmp r0, r3 
    it lt 
    movlt r0, r3 
    cmp r0, #127 
    it ge 
    movge r0, #127 
    bx lr 

clamp2: 
    adds r0, r0, #127 
    mvns r3, r0 
    and r0, r0, r3, asr #31 
    subs r0, r0, #254 
    and r0, r0, r0, asr #31 
    adds r0, r0, #127 
    bx lr 

दोनों एआरएम के सशर्त निष्पादन डिजाइन करने के लिए शाखा धन्यवाद कर रहे हैं। मैं आपको शर्त लगाऊंगा कि वे अनिवार्य रूप से प्रदर्शन में तुलनीय हैं।

+1

मेरे पास इस समय मेरे ऊपर कोई एआरएम बोर्ड नहीं है, लेकिन मैं यह देखने के लिए उत्सुक होगा कि इन चार संस्करणों के बीच प्रदर्शन अंतर क्या है। (मेरा पैसा एआरएम 'क्लैंप 1 'पर है, लेकिन अंतर अविश्वसनीय रूप से मिनट होने जा रहे हैं)। – nneonneo

3

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

एक PDF मैं दूसरे दिन (http://simplemachines.it/doc/arm_inst.pdf की pg14) डाउनलोड किया है,

सशर्त निष्पादन

  • अधिकांश अनुदेश केवल शाखाओं सशर्त क्रियान्वित किया जा करने की अनुमति सेट के शब्दों में।
  • हालांकि स्थिति मूल्यांकन हार्डवेयर का पुन: उपयोग करके, एआरएम प्रभावी ढंग से निर्देशों की संख्या बढ़ाता है।
  • सभी निर्देशों में एक शर्त फ़ील्ड होता है जो निर्धारित करता है कि CPU उन्हें निष्पादित करेगा या नहीं।
  • गैर-निष्पादित निर्देश 1 चक्र को सूखते हैं। - अभी भी चक्र को पूरा करना है ताकि निम्नलिखित निर्देशों को लाने और डीकोडिंग की अनुमति मिल सके।
  • यह कई शाखाओं की आवश्यकता को हटा देता है, जो पाइपलाइन (3 चक्रों को फिर से भरने) को रोकता है।
  • शाखाओं के बिना, बहुत घने इन-लाइन कोड की अनुमति देता है।
  • कई सशर्त निर्देशों को निष्पादित करने का समय दंड अक्सर शाखा या उपरोक्त कॉल के ऊपरी हिस्से से कम होता है जिसे अन्यथा आवश्यकतानुसार किया जाता है।
+2

खैर, तकनीकी रूप से, शाखाएं अभी भी एआरएम पर महंगी हैं। लेकिन, सशर्त निष्पादन बहुत कम कूद को खत्म कर सकता है। – nneonneo

+1

बहुत सच है, मैं सक्षम होने की तुलना में संक्षेप में बेहतर काम करने के लिए धन्यवाद। आपने इसे मुझसे कहीं अधिक संक्षेप में रखा है। :थम्स अप: – enhzflep

0

नहीं। सी भाषा में गति नहीं है; यह एक अवधारणा है जिसे सी के कार्यान्वयन द्वारा पेश किया गया है। एक पूरी तरह से इष्टतम कंपाइलर उन दोनों को एक ही मशीन कोड में अनुवाद करेगा।

सी कंपाइलर्स सामान्य शैलियों के अनुरूप कोड अनुकूलित करने में सक्षम होने की अधिक संभावना है और अच्छी तरह परिभाषित है। दूसरा कार्य अच्छी तरह परिभाषित नहीं है।

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

& और >> ऑपरेटरों के पास हस्ताक्षरित प्रकारों के लिए कार्यान्वयन-परिभाषित पहलू हैं। उनका परिणाम नकारात्मक-शून्य हो सकता है, जो एक जाल प्रतिनिधित्व का एक उदाहरण है। जाल प्रतिनिधित्व का उपयोग करना अनिर्धारित व्यवहार है, इसलिए आपका प्रोग्राम इसकी अखंडता खो सकता है।

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

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

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