कौन सा तेज है: x << 1 या x << 10?


83

मैं कुछ भी अनुकूलित नहीं करना चाहता, मैं कसम खाता हूं, मैं इस सवाल को जिज्ञासा से बाहर करना चाहता हूं। मैं जानता हूँ कि थोड़ा-शिफ्ट (जैसे की एक सभा आदेश है कि ज्यादातर हार्डवेयर पर shl, shr) है, जो एक भी आदेश है। लेकिन क्या यह मायने रखता है (नैनोसेकंड-वार, या सीपीयू-टैक-वार) आप कितने बिट्स शिफ्ट करते हैं। दूसरे शब्दों में, किसी भी सीपीयू पर या तो तेजी से निम्नलिखित है?

x << 1;

तथा

x << 10;

और कृपया इस प्रश्न के लिए मुझसे घृणा न करें। :)


17
ओमग, मैंने कोड को देखा और मेरा पहला विचार "स्ट्रीम प्रिंटिंग ऑपरेटर" था। मुझे एक अवकाश की आवश्यकता है।
कोस

4
मुझे लगता है कि मैं किसी को "समय से पहले अनुकूलन" कहते हुए सुनता हूं, उनके दिमाग में या शायद सिर्फ मेरी कल्पना है।
तिया

5
@ उन्होंने कहा कि वह कुछ भी अनुकूलन नहीं करने वाले थे :)

1
@Grigory हाँ और यही कारण है कि हम यहाँ किसी को भी उस वाक्यांश के साथ सवाल छोड़ते हुए नहीं देखते हैं। : D
tia

1
एक सनद के रूप में: मैंने हाल ही में मान्यता दी है कि बाईं ओर शिफ्टिंग और दाईं ओर शिफ्टिंग आवश्यक रूप से समान सीपीयू-टाइम का उपभोग नहीं करता है। मेरे मामले में सही शिफ्टिंग बहुत धीमी थी। पहले मुझे आश्चर्य हुआ लेकिन मुझे लगता है कि इसका उत्तर यह है कि बायाँ शिफ्टिंग का अर्थ है तार्किक और सही स्थानांतरण का अर्थ अंकगणित हो सकता है: stackoverflow.com/questions/141525/…
क्रिश्चियन आमेर

जवाबों:


84

सीपीयू पर संभावित रूप से निर्भर करता है।

हालांकि, सभी आधुनिक सीपीयू (x86, एआरएम) एक "बैरल शिफ्टर" का उपयोग करते हैं - विशेष रूप से निरंतर समय में मनमाना बदलाव करने के लिए डिज़ाइन किया गया एक हार्डवेयर मॉड्यूल।

तो लब्बोलुआब यह है ... नहीं। कोई फर्क नहीं।


21
महान, अब मेरे पास अपने सीपीयू को मेरे सिर में फंसे एक बैरल रोल करने के लिए कहने की एक छवि है ...
इग्नासियो वाज़केज़-अब्राम्स

11
त्रुटि - बहुत बहुत प्रोसेसर पर निर्भर करता है। कुछ प्रोसेसरों पर यह निरंतर समय होता है। दूसरों पर यह एक चक्र प्रति बदलाव हो सकता है (मैंने एक बार प्रोसेसर घड़ी घड़ी को मापने के तरीके के रूप में लगभग 60,000 स्थानों पर एक पारी का उपयोग किया था)। और अन्य प्रोसेसरों पर, केवल सिंगल बिट शिफ्ट्स के लिए निर्देश हो सकते हैं, जिस स्थिति में एक मल्टी-बिट शिफ्ट एक लाइब्रेरी रूटीन को सौंप दिया जाता है, जो दूर चलने वाले लूप में बैठता है।
जल्‍दी से जल्‍दी से जल्‍दी

4
@quickly_now: यह सुनिश्चित है कि घड़ी की गति को मापने का एक बुरा तरीका है। कोई प्रोसेसर वास्तव में 60,000 शिफ्ट करने के लिए पर्याप्त बेवकूफ नहीं है; वह बस में परिवर्तित हो जाएगा 60000 mod register_size। उदाहरण के लिए, एक 32-बिट प्रोसेसर शिफ्ट काउंट के 5 सबसे महत्वपूर्ण बिट्स का उपयोग करेगा।
कैसाब्लांका

4
इनमॉस ट्रांसप्यूटर में एक शिफ्ट ऑपरेटर होता था जो शिफ्ट की संख्या लेता था जो एक 32 बिट ऑपरेंड होता है। यदि आप चाहते हैं कि आप 1 घड़ी में 4 बिलियन शिफ्ट कर सकें। "कोई भी प्रोसेसर पर्याप्त बेवकूफ नहीं है"। खेद है, गलत है। यह एक किया। हालाँकि, आपको उस भाग को कोडांतरक में कोड करना होगा। संकलक ने एक समझदार संशोधन / अनुकूलन किया (केवल परिणाम को 0 पर सेट करें, कुछ भी न करें)।
जल्दी से 1

5
पेंटियम 4 ने बैरल शिफ्टर को खो दिया, दुख की बात है, जिसने इसकी संपूर्ण खराब निर्देश-प्रति-घड़ी की दर में योगदान दिया। मुझे लगता है कि कोर ब्लाह वास्तुकला को वापस मिल गया।
रसेल बोरोगोव

64

कुछ एम्बेडेड प्रोसेसर में केवल "शिफ्ट-बाय-वन" निर्देश होता है। ऐसे प्रोसेसर पर, संकलक में बदल x << 3जाएगा ((x << 1) << 1) << 1

मुझे लगता है कि मोटोरोला MC68HCxx इस सीमा के साथ अधिक लोकप्रिय परिवारों में से एक था। सौभाग्य से, इस तरह के आर्किटेक्चर अब काफी दुर्लभ हैं, अधिकांश में एक वैरिएबल शिफ्ट आकार के साथ बैरल शिफ्टर शामिल है।

इंटेल 8051, जिसमें कई आधुनिक व्युत्पन्न हैं, भी बिट्स की एक मनमानी संख्या को स्थानांतरित नहीं कर सकते हैं।


12
अभी भी एम्बेडेड माइक्रोकंट्रोलर पर आम है।
बेन जैक्सन

4
"दुर्लभ" के तहत आपका क्या मतलब है? तदनुसार, बेची गई 8-बिट माइक्रोकंट्रोलर की सांख्यिकी संख्या अन्य सभी प्रकार के एमपीयू की संख्या से अधिक है।
वोवनियम

नए विकास के लिए 8-बिट माइक्रोकंट्रोलर्स का उपयोग बहुत अधिक नहीं किया जा रहा है, जब आप प्रति प्रोग्राम एक ही कीमत के लिए 16-बिट प्राप्त कर सकते हैं (उदाहरण के लिए टीएस से एमएसपी 430) अधिक प्रोग्राम रोम, अधिक काम करने वाली रैम और अधिक क्षमता के साथ। और यहां तक ​​कि कुछ 8-बिट माइक्रोकंट्रोलर्स में बैरल शिफ्टर्स होते हैं।
बेन वोइग्ट

1
एक माइक्रोकंट्रोलर के आकार का कोई संबंध नहीं है कि इसमें बैरल शिफ्टर है, मैंने जो MC68HCxx परिवार का उल्लेख किया है उसमें 16-बिट प्रोसेसर हैं, उन सभी को एक ही बार में केवल एक ही बिट स्थान बदलते हैं।
बेन वोइगट

तथ्य यह है कि अधिकांश 8-बिट MCU में कोई बैरल शिफ्टर नहीं है, हालांकि आप सही कह रहे हैं कि थिच के लिए यह सच नहीं है, और बैरल शिफ्टर के बिना गैर-बिट हैं। गवाह [बाहर] बैरल शिफ्टर के साथ मशीनों के लिए एक विश्वसनीय सन्निकटन के रूप में मिला। यह भी तथ्य है कि एमसीयू के लिए सीपीयू कोर अक्सर मॉडल के लिए एक विकल्प निर्धारित नहीं करता है, लेकिन ऑन-चिप परिधीय होता है। और 8-बिट को अक्सर एक ही कीमत के लिए अधिक समृद्ध परिधीयों के लिए चुना जाता है।
Vovanium

29

इस पर कई मामले हैं।

  1. कई हाई-स्पीड एमपीयू में बैरल शिफ्टर, मल्टीप्लेक्स-जैसे इलेक्ट्रॉनिक सर्किट होते हैं जो निरंतर समय में किसी भी बदलाव को करते हैं।

  2. यदि MPU में केवल 1 बिट शिफ्ट x << 10सामान्य रूप से धीमी होगी, क्योंकि यह ज्यादातर 10 शिफ्ट्स या बाइट की नकल 2 शिफ्ट्स के साथ की जाती है।

  3. लेकिन वहाँ आम मामला है जहाँ x << 10से भी तेजी से जाना जाता है x << 1। यदि x 16 बिट है, तो केवल 6 बिट्स की देखभाल होती है (अन्य सभी को बाहर स्थानांतरित कर दिया जाएगा), इसलिए MPU को केवल लोअर बाइट को लोड करने की आवश्यकता होती है, इस प्रकार 8-बिट मेमोरी में केवल सिंगल एक्सेस साइकिल बनाते हैं, जबकि x << 10दो एक्सेस साइकल की आवश्यकता होती है। यदि पहुंच चक्र शिफ्ट (और स्पष्ट लोअर बाइट) की तुलना में धीमा है, x << 10तो तेज हो जाएगा। यह धीमी गति से बाहरी डेटा रैम तक पहुंचने के दौरान फास्ट ऑनबोर्ड प्रोग्राम रोम के साथ माइक्रोकंट्रोलर पर लागू हो सकता है।

  4. केस 3 के अतिरिक्त, कंपाइलर x << 10कम-चौड़ाई वाले लोगों के लिए महत्वपूर्ण बिट्स की संख्या की देखभाल कर सकता है और 16x8 एक के साथ 16x16 गुणा की जगह ले सकता है (जैसा कि निचला बाइट हमेशा शून्य होता है)।

ध्यान दें, कुछ माइक्रोकंट्रोलर्स के पास कोई शिफ्ट-लेफ्ट इंस्ट्रक्शन नहीं होता है, वे add x,xइसके बजाय उपयोग करते हैं।


मुझे नहीं पता है, क्यों x << 10 तेज है तो x << 8 जहां x << 8 में आपको कम बाइट से 16 बिट से एक लोड करने की ज़रूरत है, और लोड और दो शिफ्ट नहीं करना है। मुझे नहीं मिला।
कोई

3
@ कोई: मैंने यह नहीं बताया कि x << 10 x << 8 से अधिक तेज है।
वॉनियम

9

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


1
क्या निर्देश समान चक्रों में निष्पादित होते हैं? कुछ आर्किटेक्चर पर एक ही निर्देश ऑपरेंड के आधार पर कुछ अलग ऑप-कोड में अनुवाद करेगा, और 1 से 5 चक्र तक कहीं भी ले जाएगा।
निक टी

@ एक एआरएम निर्देश आमतौर पर 1 या 2 चक्रों के बीच होता है। नए आर्किटेक्चर के साथ यकीन नहीं है।
रात

2
@ निक टी: वह एआरएम के बारे में बोल रहा है, जो समर्पित निर्देश के रूप में नहीं, बल्कि कई डेटा प्रोसेसिंग निर्देशों के 'फीचर' के रूप में है। यानी ADD R0, R1, R2 ASL #3R1 और R2 को 3 बिट्स बचे हुए स्थानांतरित कर दिया।
वोवेन नोव

9

यहाँ मेरा पसंदीदा CPU है , जिसमें x<<2दो बार लंबे समय तक x<<1:)


दुर्भाग्यवश इसमें 8051, PIC या AVR जैसा एक नीच स्वैप निर्देश नहीं है, इसलिए ऑप्टिमाइज़ेशन ट्रिक का उपयोग नहीं किया जा सकता है
phuclv

7

यह सीपीयू और कंपाइलर दोनों पर निर्भर करता है। यहां तक ​​कि अगर अंतर्निहित सीपीयू में बैरल शिफ्टर के साथ मनमाना बिट शिफ्ट है, तो यह केवल तभी होगा जब कंपाइलर उस संसाधन का लाभ उठाएगा।

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

ANSI C खंड 3.3.7 से उद्धरण:

3.3.7 बिटवाइज़ शिफ्ट ऑपरेटर

वाक्य - विन्यास

      shift-expression:
              additive-expression
              shift-expression <<  additive-expression
              shift-expression >>  additive-expression

प्रतिबन्ध

प्रत्येक ऑपरेंड का अभिन्न प्रकार होगा।

शब्दार्थ

प्रत्येक प्रचालन पर अभिन्न पदोन्नति की जाती है। परिणाम का प्रकार पदोन्नत बाएं ऑपरेंड है। यदि सही ऑपरेंड का मान नकारात्मक है या पदोन्नत किए गए बाएं ऑपरेंड के बिट्स में चौड़ाई के बराबर या उससे अधिक है, तो व्यवहार अपरिभाषित है।

E1 << E2 का परिणाम E1 वाम-शिफ्ट किया गया E2 सा स्थान है; खाली बिट्स शून्य से भरे हुए हैं। यदि E1 का एक अहस्ताक्षरित प्रकार है, तो परिणाम का मान E1 की मात्रा से गुणा किया जाता है, 2 को E2 की शक्ति तक बढ़ा दिया जाता है, modulo ULONG_MAX + 1 को कम कर दिया जाता है, यदि E1 में अहस्ताक्षरित प्रकार लंबा है, तो UINT_MAX + 1 अन्यथा। (कॉन्स्टेंट ULONG_MAX और UINT_MAX हेडर में परिभाषित किए गए हैं।)

E1 >> E2 का परिणाम E1 सही-स्थानांतरित E2 बिट स्थिति है। यदि E1 में एक अहस्ताक्षरित प्रकार है या यदि E1 में एक हस्ताक्षरित प्रकार और एक नॉनजेगेटिव वैल्यू है, तो परिणाम का मान E1 के भाग की मात्रा का अभिन्न हिस्सा है, 2 को शक्ति E2 तक बढ़ा दिया गया है। यदि E1 में एक हस्ताक्षरित प्रकार और एक नकारात्मक मूल्य है, तो परिणामी मूल्य कार्यान्वयन-परिभाषित है।

इसलिए:

x = y << z;

"<<": y × 2 z ( यदि अतिप्रवाह होता है तो अपरिभाषित );

x = y >> z;

">": हस्ताक्षर के लिए कार्यान्वयन-परिभाषित (ज्यादातर अंकगणितीय पारी का परिणाम: y / 2 z )।


मुझे नहीं लगता 1u << 100कि यूबी है। यह सिर्फ 0. है
अर्मेन Tsirunyan

@ अर्मेन त्सिरुयन: एक बिट शिफ्ट के 1u << 100रूप में एक अतिप्रवाह हो सकता है; 1u << 100अंकगणितीय पारी के रूप में 0. एएनएसआई सी के तहत, <<एक सा बदलाव है। en.wikipedia.org/wiki/Arithmetic_shift
भेड़िया

2
@ अर्मेन त्सिरुयन: एएनएसआई अनुभाग 3.3.7 देखें - यदि सही ऑपरेंड का मूल्य नकारात्मक है या पदोन्नत किए गए बाएं ऑपरेंड के बिट्स में चौड़ाई के बराबर या उससे अधिक है, तो व्यवहार अपरिभाषित है। तो आपका उदाहरण किसी भी ANSI C सिस्टम पर UB है जब तक कि 101+ बिट प्रकार न हो।
भेड़िया

@ गाजर-पॉट: ठीक है, आपने मुझे मना लिया :)
आर्मेन त्सिरुयन

संबंधित: x << (y & 31)अभी भी बिना और निर्देश के साथ एक एकल शिफ्ट निर्देश को संकलित कर सकता है, यदि कंपाइलर को पता है कि लक्ष्य आर्किटेक्चर की शिफ्ट इंस्ट्रक्शन गिनती (जैसे कि x86 करता है) मास्क करता है। (अधिमानतः मास्क को हार्ड-कोड न करें, इसे CHAR_BIT * sizeof(x) - 1या कुछ और से प्राप्त करें ।) यह एक घुमाए गए मुहावरे को लिखने के लिए उपयोगी है जो इनपुट के बिना किसी भी सी यूबी के बिना एक निर्देश को संकलित करता है। ( stackoverflow.com/questions/776508/… )।
पीटर कॉर्ड्स

7

यह अनुमान योग्य है कि, 8-बिट प्रोसेसर पर, x<<1वास्तव में की तुलना में बहुत धीमा हो सकता हैx<<10 16-बिट मूल्य के ।

उदाहरण के लिए एक उचित अनुवाद x<<1हो सकता है:

byte1 = (byte1 << 1) | (byte2 >> 7)
byte2 = (byte2 << 1)

जबकि x<<10अधिक सरल होगा:

byte1 = (byte2 << 2)
byte2 = 0

ध्यान दें कि कैसे x<<1अधिक से अधिक बार और यहां तक ​​कि की तुलना में दूर स्थानांतरित करता है x<<10। इसके अलावा x<<10बाइट 1 की सामग्री पर निर्भर नहीं करता है। यह अतिरिक्त रूप से ऑपरेशन को गति दे सकता है।


5

इंटेल सीपीयू (पी 2 या पी 3? नहीं एएमडी की कुछ पीढ़ियों पर, अगर मुझे सही याद है), तो बिटशिफ्ट ऑपरेशन धीमी गति से हास्यास्पद हैं। बिटशफ्ट 1 बिट से हमेशा तेज होना चाहिए, क्योंकि यह सिर्फ इसके अतिरिक्त उपयोग कर सकता है। विचार करने के लिए एक और सवाल है कि क्या बिट्स की एक निरंतर संख्या से बिट्स शिफ्ट चर-लंबाई की बदलावों की तुलना में तेज हैं। भले ही opcodes एक ही गति हो, x86 पर बिटशिफ्ट के गैरसंवैधानिक दाह संस्कार सीएल रजिस्टर पर कब्जा करना चाहिए, जो रजिस्टर आवंटन पर अतिरिक्त अवरोध लगाता है और इस तरह से कार्यक्रम को धीमा भी कर सकता है।


1
वह पेंटियम 4. पीपीआर-व्युत्पन्न सीपीयू (जैसे पी 2 और पी 3) में तेज बदलाव है। और हाँ, x86 पर चर-गणना बदलाव धीमी गति से होते हैं, जब तक कि आप BMI2 shlx/ shrx/ sarx(Haswell और बाद में, और Ryzen) का उपयोग नहीं कर सकते । CISC शब्दार्थ (झंडे अनमॉडिफाइड यदि गिनती = 0) यहाँ x86 को चोट पहुँचाते हैं। shl r32, clसैंडीब्रिज-परिवार पर 3 यूओपी है (हालांकि इंटेल का दावा है कि यदि झंडा परिणाम अप्रयुक्त है तो यह किसी एक को रद्द कर सकता है)। एएमडी में एकल-यूओपी shl r32, cl(लेकिन विस्तारित-परिशुद्धता के लिए धीमी गति से डबल-शिफ्ट shld r32, r32, cl) है
पीटर कॉर्डेस

1
शिफ्ट्स (यहां तक ​​कि वेरिएबल-काउंट) भी पी 6-परिवार पर केवल एक यूओपी हैं, लेकिन शिफ्ट के रिटायर होने तक फ्रंट-एंड केshl r32, cl स्टॉल के साथ या उसके तत्काल बाद दूसरे फ्लैग-रिजल्ट को पढ़ना ! ( stackoverflow.com/questions/36510095/… )। कंपाइलर इसे जानते हैं, और एक शिफ्ट के ध्वज परिणाम का उपयोग करने के बजाय एक अलग निर्देश का उपयोग करते हैं। (लेकिन यह सीपीयू पर निर्देशों को बर्बाद करता है जहां यह कोई समस्या नहीं है, देखें stackoverflow.com/questions/40354978/… )test
पीटर कॉर्ड्स

3

हमेशा की तरह, यह आसपास के कोड के संदर्भ पर निर्भर करता है : उदाहरण के लिए आप x<<1एक सरणी इंडेक्स के रूप में उपयोग कर रहे हैं ? या इसे किसी और चीज़ से जोड़ रहे हैं? या तो मामले में, छोटी शिफ्ट मायने रखता है (1 या 2) अक्सर तुलना में अधिक अनुकूलित कर सकते हैं अगर कंपाइलर सिर्फ शिफ्ट होने के लिए समाप्त होता है । संपूर्ण थ्रूपुट बनाम विलंबता बनाम फ्रंट-एंड अड़चनों के व्यापार का उल्लेख नहीं करना। एक छोटे टुकड़े का प्रदर्शन एक आयामी नहीं है।

एक हार्डवेयर शिफ्ट निर्देश संकलन करने के लिए एक कंपाइलर का एकमात्र विकल्प नहीं है x<<1, लेकिन अन्य उत्तर ज्यादातर यही मान रहे हैं।


x << 1x+xअहस्ताक्षरित के लिए, और 2 के पूरक हस्ताक्षरित पूर्णांक के बराबर है । कंपाइलर हमेशा जानते हैं कि वे संकलन करते समय किस हार्डवेयर को लक्षित कर रहे हैं, इसलिए वे इस तरह से ट्रिक्स का लाभ उठा सकते हैं।

पर इंटेल Haswell , addघड़ी प्रवाह क्षमता प्रति 4 है, लेकिन shlएक तत्काल गिनती के साथ ही 2 घड़ी प्रवाह क्षमता प्रति है। (देख निर्देश तालिका के लिए http://agner.org/optimize/ और अन्य लिंकटैग विकि)। SIMD वेक्टर शिफ़्ट 1 प्रति घड़ी (Skylake में 2) हैं, लेकिन SIMD वेक्टर पूर्णांक 2 प्रति घड़ी (Skylake में 3) हैं। विलंबता समान है, हालांकि: 1 चक्र।

एक विशेष शिफ्ट-बाय-वन एन्कोडिंग भी है shlजहां गिनती को ओपोड में निहित किया गया है। ० have६ में केवल और बाद में clरजिस्टर द्वारा तत्काल-गणना की पारियां नहीं थीं । यह ज्यादातर राइट-शिफ्ट्स के लिए प्रासंगिक है, क्योंकि आप केवल लेफ्ट शिफ्ट्स के लिए जोड़ सकते हैं, जब तक कि आप मेमोरी ऑपरेंड शिफ्ट नहीं कर रहे हैं। लेकिन अगर बाद में मूल्य की आवश्यकता होती है, तो पहले एक रजिस्टर में लोड करना बेहतर होता है। लेकिन वैसे भी, shl eax,1या add eax,eaxएक बाइट से कम है shl eax,10, और कोड-आकार सीधे (डिकोड / फ्रंट-एंड अड़चनें) या अप्रत्यक्ष रूप से (एल 1 आई कोड कैश मिस) प्रदर्शन को प्रभावित कर सकता है।

अधिक आम तौर पर, छोटी पारी की गणना को कभी-कभी x86 पर एक संबोधित मोड में स्केल किए गए सूचकांक में अनुकूलित किया जा सकता है। इन दिनों आम उपयोग में आने वाले अधिकांश अन्य आर्किटेक्चर RISC हैं, और स्केल-इंडेक्स एड्रेसिंग मोड नहीं हैं, लेकिन x86 इसके लिए एक सामान्य पर्याप्त वास्तुकला है। (यदि आप 4-बाइट तत्वों की एक सरणी को अनुक्रमित कर रहे हैं, तो स्केल कारक को 1 के लिए बढ़ाने के लिए जगह है int arr[]; arr[x<<1])।


जिन परिस्थितियों xमें अभी भी मूल मूल्य की आवश्यकता है, उन स्थितियों में कॉपी + शिफ्ट की आवश्यकता आम है । लेकिन अधिकांश x86 पूर्णांक निर्देश जगह-जगह काम करते हैं। (जैसे addया जैसे निर्देशों के लिए गंतव्य एक है shl।) x86-64 सिस्टम V कॉलिंग कन्वेंशन रजिस्टरों में आर्ग में गुजरता है, जिसमें पहला एर्ग इन ediऔर रिटर्न वैल्यू होता है eax, इसलिए एक फ़ंक्शन जो रिटर्न x<<10भी कंपाइलर एमिट कॉपी + शिफ्ट करता है। कोड।

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

gcc और clang दोनों इन कार्यों को उसी तरह अनुकूलित करते हैं, जैसा कि आप Godbolt कंपाइलर एक्सप्लोरर पर देख सकते हैं :

int shl1(int x) { return x<<1; }
    lea     eax, [rdi+rdi]   # 1 cycle latency, 1 uop
    ret

int shl2(int x) { return x<<2; }
    lea     eax, [4*rdi]    # longer encoding: needs a disp32 of 0 because there's no base register, only scaled-index.
    ret

int times5(int x) { return x * 5; }
    lea     eax, [rdi + 4*rdi]
    ret

int shl10(int x) { return x<<10; }
    mov     eax, edi         # 1 uop, 0 or 1 cycle latency
    shl     eax, 10          # 1 uop, 1 cycle latency
    ret

2 घटकों के साथ LEA में हाल ही के इंटेल और AMD CPU पर 1 चक्र विलंबता और 2-प्रति-घड़ी थ्रूपुट है। (सैंडब्रिज-परिवार और बुलडोजर / रायज़ेन)। इंटेल पर, यह केवल 1 प्रति घड़ी थ्रूपुट है जिसमें 3 सी विलंबता है lea eax, [rdi + rsi + 123]। (संबंधित: Collatz अनुमान के परीक्षण के लिए मेरे हाथ से लिखे गए विधानसभा की तुलना में यह C ++ कोड अधिक तेज़ क्यों है? इस बारे में विस्तार से बताया गया है।)

वैसे भी, कॉपी + शिफ्ट में 10 अलग movनिर्देश की जरूरत होती है । यह कई हालिया सीपीयू पर शून्य विलंबता हो सकता है, लेकिन यह अभी भी फ्रंट-एंड बैंडविड्थ और कोड आकार लेता है। ( क्या x86 का MOV वास्तव में "मुक्त" हो सकता है? मैं इसे क्यों नहीं पुन: पेश कर सकता हूं? )

यह भी संबंधित: x86 में केवल 2 लगातार leal निर्देशों का उपयोग करके एक रजिस्टर को 37 से गुणा कैसे करें?


कंपाइलर आसपास के कोड को बदलने के लिए भी स्वतंत्र है इसलिए वास्तविक शिफ्ट नहीं है, या यह अन्य ऑपरेशन के साथ संयुक्त है

उदाहरण के लिए उच्च बिट को छोड़कर सभी बिट्स की जांच करने के if(x<<1) { }लिए एक andका उपयोग कर सकते हैं । X86 पर, आप एक testनिर्देश का उपयोग करेंगे , जैसे test eax, 0x7fffffff/ के jz .falseबजाय shl eax,1 / jz। यह अनुकूलन किसी भी शिफ्ट काउंट के लिए काम करता है, और यह उन मशीनों पर भी काम करता है, जहाँ बड़ी-बड़ी पारियाँ धीमी होती हैं (जैसे पेंटियम 4), या गैर-मौजूद (कुछ माइक्रो-कंट्रोलर)।

कई आईएसएएस में केवल स्थानांतरण से परे बिट-हेरफेर निर्देश हैं। जैसे कि पावरपीसी में बहुत सारे बिट-फिल्ड एक्सट्रैक्ट / इन्सर्ट निर्देश हैं। या एआरएम के पास किसी अन्य अनुदेश के हिस्से के रूप में स्रोत ऑपरेंड की शिफ्ट्स हैं। (इसलिए शिफ्ट / रोटेट निर्देश moveशिफ्ट किए गए स्रोत का उपयोग करते हुए सिर्फ एक विशेष रूप है ।)

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

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