2011-11-15 11 views
10

में% ऑपरेटर और/ऑपरेटर का उपयोग करने के लिए वैकल्पिक यह बताया गया है कि मॉड्यूल ऑपरेटर "%" और विभाजित ऑपरेटर "/" एम्बेडेड सी ++ में बहुत अक्षम हैं।सी ++

मैं कैसे वैकल्पिक रूप से निम्नलिखित अभिव्यक्ति को प्राप्त कर सकते हैं:

a = b % c; 

मैं समझता हूँ कि इस निम्न तर्क का प्रयोग कर प्राप्त किया जा सकता:

a = b - c; 
while (a >= c) { 
    a = a - c; 
} 

लेकिन मेरे सवाल है, while लूप में शामिल इस कोड है % ऑपरेटर की तुलना में पर्याप्त कुशल?

धन्यवाद, कीर्ति

+0

"% ऑपरेटर की तुलना करते हुए पर्याप्त कुशल छोरों से जुड़े इस कोड है?" आप हमें बताते हैं, आप प्रोग्राम का उपयोग कर रहे हैं। क्या यह धीमा लगता है? क्या आप भी ध्यान दे सकते हैं? क्या आपने प्रोफाइल किया है और यह धीमा होने के लिए पाया है? – GManNickG

+2

वह आकार पर निर्भर करेगा। यदि 'बी = 1000000000' और' सी = 3'। इसमें कुछ समय लगेगा ... – Mysticial

+0

क्या आप लक्ष्य सीपीयू और कंपाइलर बता सकते हैं? इसके बिना किसी भी दृष्टिकोण की तुलना करना असंभव है। – fghj

उत्तर

7

कुछ भी नहीं % ऑपरेटर की तुलना में काफी अधिक कुशल होने जा रहा है। यदि ऐसा करने का एक बेहतर तरीका था, तो कोई भी उचित कंपाइलर स्वचालित रूप से इसे परिवर्तित कर देगा। जब आपको बताया जाता है कि % और / अक्षम हैं, तो ऐसा इसलिए है क्योंकि ये कठिन परिचालन हैं - यदि आपको मॉड्यूलो करने की आवश्यकता है, तो ऐसा करें।

बेहतर तरीके होने पर विशेष मामले हो सकते हैं - उदाहरण के लिए, दो की शक्ति बाइनरी के रूप में लिखी जा सकती है या - लेकिन शायद आपके कंपाइलर द्वारा अनुकूलित किया जा सकता है।

18

डिवीजन और मॉड्यूलस वास्तव में महंगा हार्डवेयर ऑपरेशंस हैं, जो भी आप करते हैं (यह भाषा या कंपाइलर्स की तुलना में हार्डवेयर आर्किटेक्चर से अधिक संबंधित है), शायद दस गुना धीमी गति से धीमा है।

हालांकि, मौजूदा लैपटॉप या सर्वर पर, और उच्च अंत माइक्रोकंट्रोलर पर, cache मिस अक्सर विभाजन से बहुत धीमे होते हैं!

जीसीसी कंपाइलर प्रायः उन्हें अनुकूलित करने में सक्षम होता है, जब विभाजक स्थिर होता है।

आपका बेवकूफ पाश आमतौर पर हार्डवेयर विभाजन निर्देश (या लाइब्रेरी दिनचर्या, हार्डवेयर द्वारा प्रदान नहीं किए जाने पर) का उपयोग करने से कहीं अधिक धीमी है। मेरा मानना ​​है कि आप अपने लूप के साथ विभाजन & से बचने में गलत हैं।

आप अपने एल्गोरिदम को ट्यून कर सकते हैं -e.g. दो की शक्ति होने से- लेकिन मैं आपके कोड का उपयोग करने की अनुशंसा नहीं करता हूं। याद रखें कि समयपूर्व अनुकूलन बुराई है इसलिए सबसे पहले अपने प्रोग्राम को सही करने का प्रयास करें, फिर परेशानी के स्थानों को ढूंढने के लिए इसे प्रोफ़ाइल करें।

+0

+1। कई असफल परियोजनाओं का कारण। – Dan

+1

उद्धरण पूर्ण होने पर बेहतर होते हैं: * हमें छोटी क्षमता के बारे में भूल जाना चाहिए, समय के बारे में 9 7% कहें: समयपूर्व अनुकूलन सभी बुराई की जड़ है, अन्यथा अच्छा जवाब। –

5

यह कोड लगभग निश्चित रूप से धीमा हो जाएगा, हालांकि आपका प्रोसेसर/कंपाइलर विभाजन/मोड करने का निर्णय लेता है। आम तौर पर, शॉर्टकट मूल अंकगणितीय ऑपरेटरों के लिए आने के लिए बहुत कठिन होते हैं, क्योंकि एमसीयू/सीपीयू डिजाइनर और कंपाइलर प्रोग्रामर लगभग सभी अनुप्रयोगों के लिए इसे अनुकूलित करने में बहुत अच्छे हैं।

एम्बेडेड डिवाइसों में एक आम शॉर्टकट (जहां प्रत्येक चक्र/बाइट एक अंतर कर सकता है) बिट-शिफ्ट ऑपरेटरों का उपयोग गुणा और विभाजन करने के लिए, और बिटवाई और() करने के लिए सब कुछ रखना है। मॉड्यूलो करने के लिए।

उदाहरण:

unsigned int x = 100; 
unsigned int y1 = x << 4; // same as x * 2^4 = x*16 
unsigned int y2 = x >> 6; // same as x/2^6 = x/64 
unsigned int y3 = x & 0x07; // same as x % 8 
+3

कोई भी सभ्य कंपाइलर आपके लिए वही अनुकूलन करेगा जब सही ऑपरेंड एक शक्ति-दो-स्थिर है। बिट-स्थानांतरण/मास्किंग चाल शुरुआती दिनों से बचे हुए है जब संकलक अनुकूलन चूसा जाता है, और अब आवश्यक नहीं होना चाहिए। –

+0

एम्बेडेड दुनिया में दुर्भाग्यवश हमेशा एक सभ्य कंपाइलर की विलासिता नहीं होती है ... मैं सामान्य मामले में सहमत हूं, लेकिन जब संदेह है, तो असंतुलन की त्वरित जांच यह निर्धारित करेगी कि इससे मदद मिलेगी या नहीं। – shenles

1

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

0

डिवीजन एक निरंतर द्वारा एक पारी से प्राप्त किया जा सकता है, तो 2 के एक शक्ति या दूसरों के लिए एक mul ऐड पारी संयोजन।

http: // masm32.com/board/index.php?topic=9937.0 पहली पोस्ट से डाउनलोड में 86 विधानसभा संस्करण के साथ ही सी स्रोत है। जो आपके लिए यह कोड उत्पन्न करता है।

1

आप अपने कोड को ध्यान से प्रोफाइल और पाया कि एक सापेक्ष ऑपरेटर एक आंतरिक पाश में प्रमुख लागत है है, तो वहाँ एक अनुकूलन है कि मदद कर सकता है है। आप (32 बिट मूल्यों के लिए) गणित छोड़ बदलाव का उपयोग कर एक पूर्णांक के हस्ताक्षर निर्धारित करने के लिए चाल के साथ पहले से ही परिचित हो सकते हैं:

sign = (x >> 31) | 1; 

यह शब्द भर में हस्ताक्षर बिट फैली हुई है, तो ऋणात्मक मानों -1 और सकारात्मक उपज महत्व देता है 0. तो थोड़ा 0 तो सेट कर दिया जाता है कि हम केवल एक मात्रा है कि सापेक्ष तो यह एक ही चाल परिणाम रैप करने के लिए इस्तेमाल किया जा सकता से भी कम है के आधार पर मानों incrementing रहे हैं कि सकारात्मक मूल्यों में 1.

परिणाम:

val += inc; 
val -= modulo & (static_cast<int32_t>(((modulo - 1) - val)) >> 31); 
वैकल्पिक रूप से

, यदि आप कर रहे हैं decrementing सापेक्ष कम से कम मूल्यों से फिर प्रासंगिक कोड है:

int32_t signedVal = static_cast<int32_t>(val - dec); 
val = signedVal + (modulo & (signedVal >> 31)); 

मैं static_cast ऑपरेटरों जोड़ दिया है क्योंकि मैं uint32_t में गुजर रहा था, लेकिन आप उन्हें आवश्यक नहीं मिल सकती है।

इस के रूप में एक साधारण% ऑपरेटर के लिए विरोध ज्यादा मदद करता है? यह आपके कंपाइलर और सीपीयू आर्किटेक्चर पर निर्भर करता है। मैंने पाया कि वीएस2012 के तहत संकलित होने पर मेरे आई 3 प्रोसेसर पर एक साधारण पाश 60% तेज हो गया, हालांकि रास्पबेरी पीआई में एआरएम 11 चिप पर और जीसीसी के साथ संकलन में मुझे केवल 20% सुधार मिला।

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

  • कोई संबंधित समस्या नहीं^_^