2008-10-24 20 views

उत्तर

28

की शक्तियों द्वारा moduli का अनुकूलन वास्तव में VS2008 को यह अनुकूलन कर x + x:

01391000 push  ecx 
    int x = 0; 

    scanf("%d", &x); 
01391001 lea   eax,[esp] 
01391004 push  eax 
01391005 push  offset string "%d" (13920F4h) 
0139100A mov   dword ptr [esp+8],0 
01391012 call  dword ptr [__imp__scanf (13920A4h)] 

    int y = x * 2; 
01391018 mov   ecx,dword ptr [esp+8] 
0139101C lea   edx,[ecx+ecx] 

एक 64 में इसे बनाने और भी अधिक स्पष्ट है और उपयोग करता है:

int y = x * 2; 
000000013FB9101E mov   edx,dword ptr [x] 

    printf("%d", y); 
000000013FB91022 lea   rcx,[string "%d" (13FB921B0h)] 
000000013FB91029 add   edx,edx 

यह 'अधिकतम गति' (/ ओ 2)

+1

जीसीसी एक ही चीज करता है (मैंने पहले से ही लीआ का उपयोग करने के कई बार देखा है, और आपके नमूना प्रोग्राम को संकलित करते हुए इसे -m32 और -m64 दोनों के साथ जोड़ दिया गया है)। – CesarB

+0

इस जानकारी को देखने का एक त्वरित तरीका: ब्याज की रेखा पर ब्रेकपॉइंट डालें, डीबग मोड में चलाएं। जब यह लाइन पर रुक जाता है, तो राइट क्लिक करें और "डिस्सेप्लेस पर जाएं" चुनें। यहां अन्य विधियां: https://stackoverflow.com/questions/1020498/how-to-view-the-assembly-behind-the-code-using-visual-c – RoG

10

यदि एक्स एक फ्लोट नहीं है तो यह नहीं होगा।

+0

उत्कृष्ट बिंदु। –

+0

बेशक, एक फ्लोट को स्थानांतरित करने के लिए दो, n'est pas की शक्तियों से गुणा के मुकाबले एक पूरी तरह से अलग परिणाम है? – wprl

+0

2 के साथ एक फ्लोट गुणा के लिए एक्सपोनेंट में केवल 1 जोड़ने का मामला है। लेकिन मुझे नहीं लगता कि संकलक इसे अनुकूलित करते हैं। – rslite

0

हां, वे करेंगे।

4

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

+0

कंपाइलर को वास्तव में विभाजन के लिए कोई अतिरिक्त निर्देश नहीं छोड़ना पड़ता है - यही वह है जो एसएएल है - यह दो पूरक संख्याओं को सही तरीके से संभालता है। – Branan

+0

एर हाँ (जहां एसएएल द्वारा आप एसएआर मतलब था); यह 2 की शक्तियों द्वारा हस्ताक्षरित मॉड्यूलि के लिए है जिसमें यह अतिरिक्त बिट ट्विडलिंग कोड –

12

वीएस 2008 ने ऑप्टिमाइज़ेशन सेटिंग्स को x < < पर अनुकूलित किया है 1.

x = x * 2; 
004013E7 mov   eax,dword ptr [x] 
004013EA shl   eax,1 
004013EC mov   dword ptr [x],eax 

संपादित करें: यह ऑप्टिमाइज़ेशन अक्षम (/ ओडी) के साथ वीएस डिफ़ॉल्ट "डीबग" कॉन्फ़िगरेशन का उपयोग कर रहा था। किसी ऑप्टिमाइज़ेशन स्विच (/ ओ 1,/ओ 2 (वीएस "रिटेल"), या/ऑक्स का उपयोग करके) ऐड सेल्फ कोड रॉब पोस्ट किया गया है। इसके अलावा, केवल अच्छे उपाय के लिए, मैंने सत्यापित किया है कि x = x << 1 वास्तव में दोनों/ओडी और/ऑक्स में सीएल कंपाइलर द्वारा x = x * 2 जैसा व्यवहार किया जाता है। तो, संक्षेप में, x86 के लिए cl.exe संस्करण 15.00.30729.01 * 2 और << 1 समान रूप से व्यवहार करता है और मुझे उम्मीद है कि लगभग सभी अन्य हालिया कंपाइलर भी ऐसा ही करेंगे।

+0

आपको यह सूचीबद्ध करना चाहिए कि आप किस संकलन सेटिंग्स का उपयोग कर रहे थे –

-9

यह आपके पास क्या संकलक है इस पर निर्भर करता है। उदाहरण के लिए दृश्य सी ++ अनुकूलन में कुख्यात रूप से खराब है। यदि आप अपनी पोस्ट को यह कहने के लिए संपादित करते हैं कि आप किस कंपाइलर का उपयोग कर रहे हैं, तो इसका उत्तर देना आसान होगा।

+1

? सबसे पहले मैं इसके बारे में सुन रहा हूँ। असल में, मैं आमतौर पर सुनता हूं कि यह ऑप्टिमाइज़ेशन के लिए सर्वश्रेष्ठ पीसी स्तर के कंपाइलरों में से एक है। –

+2

कोई सबूत है कि वीसी ++ "अनुकूलन में कुख्यात रूप से खराब" है? उदाहरण के लिए, हमें विभिन्न कंप्यूटर्स द्वारा उसी स्रोत से उत्पन्न मशीन कोड दिखाएं। –

+1

@ जेम्स: http://www.ddj.com/184405641 <- बड़ा लेख। http://www.ddj.com/showArticle.jhtml?documentID=ddj0405a&pgno=12 <- निष्कर्ष निकालने वाली तालिका मैं यह नहीं कह रहा हूं कि यह एक लेख मानक है, लेकिन मैं लिनक्स समुदाय में हूं, मैं वीसी ++ के बारे में बुरी टिप्पणियां नहीं सुनता अक्सर, लेकिन पर्याप्त है। –

4

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

0

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

21

रेमंड चेन से यह लेख दिलचस्प हो सकता है:

जब एक्स/2 एक्स >> 1 से अलग है?: http://blogs.msdn.com/oldnewthing/archive/2005/05/27/422551.aspx

रेमंड का हवाला देते हुए:

बेशक

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

[...]

यहां तक ​​कि अगर आप को लगता है कि बदलाव संकेत बिट से भर जाता है, बदलाव और भाग का परिणाम अलग अगर एक्स नकारात्मक है कर रहे हैं।

(-1)/2 ≡ 0
(-1) >> 1 ≡ -1

[...]

कहानी का नैतिक लिखने के लिए तुम क्या मतलब है । यदि आप दो से विभाजित करना चाहते हैं, तो "/ 2" लिखें, न कि ">> 1"। संकलक बेहतर अनुकूलन के छोटे पैमाने पर कोड (के लिए धन्यवाद में एक मानव की तुलना में है:

हम केवल यह मान सकते हैं संकलक आप क्या चाहते हैं, क्या नहीं तुम उसे क्या करना चाहते हैं यह बताने के लिए बुद्धिमान है डेमिन इस सूक्ष्म बिंदु को इंगित करने के लिए): यदि आप वास्तव में अनुकूलन चाहते हैं, तो एक प्रोफाइलर का उपयोग करें, और अपने एल्गोरिदम की दक्षता का अध्ययन करें।

+1

प्रश्न पूछने वाले छोटे पैमाने पर कोड को कम से कम अनुकूलित करने के लिए, मानव को अभी भी algotirhm लिखना चाहिए :-) – Daemin

+0

@ डेमिन: आप काफी सही हैं – paercebal

+0

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

1

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

0

@ फेरूरुसीओ बरलेट

यह एक अच्छा सवाल है। मैं जवाब खोजने की कोशिश करने के लिए गुगलिंग गया।

मुझे इंटेल प्रोसेसर के लिए सीधे जवाब नहीं मिल सका, लेकिन this पृष्ठ में कोई ऐसा व्यक्ति है जिसने समय की कोशिश की। यह बदलावों को विज्ञापन और गुणा के रूप में तेज़ी से दोगुना से अधिक होने लगता है। बिट बदलाव इतनी सरल हैं (जहां एक गुणा एक शिफ्ट और एक जोड़ा हो सकता है) कि यह समझ में आता है।

तो फिर मैंने एएमडी गुगल किया, और 2002 से एथलॉन के लिए पुरानी अनुकूलन मार्गदर्शिका पाई, जिसमें सूचियां 2 से 32 के बीच contants द्वारा संख्याओं को गुणा करने के सबसे तेज़ तरीके सूचीबद्ध करती हैं। दिलचस्प बात यह है कि यह संख्या पर निर्भर करता है। कुछ विज्ञापन हैं, कुछ बदलाव। यह page 122 पर है।

Athlon 64 के लिए एक गाइड एक ही चीज़ दिखाता है (पृष्ठ 164 या तो)। यह कहता है कि गुणा 3 (32-बिट में) या 4 (64-बिट में) चक्र संचालन होते हैं, जहां बदलाव 1 होते हैं और जोड़ते हैं 2.

ऐसा लगता है कि यह अभी भी अनुकूलन के रूप में उपयोगी है।

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

लेकिन यह अनुमान है।

4

यह केवल ऑप्टिमाइज़र क्या कर सकता है इसकी शुरुआत है। यह देखने के लिए कि आपका कंपाइलर क्या करता है, स्विच के लिए देखो जो इसे असेंबलर स्रोत को उत्सर्जित करने का कारण बनता है। डिजिटल मंगल कंपाइलरों के लिए, आउटपुट असेंबलर की जांच ओबीजे 2 एएसएम उपकरण के साथ की जा सकती है।यदि आप सीखना चाहते हैं कि आपका कंपाइलर कैसे काम करता है, तो असेंबलर आउटपुट को देखते हुए बहुत रोशनी हो सकती है।

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