मुझे लगता है कि प्रश्नकर्ता के लिए अधिक विभेदित उत्तर के लिए यह अधिक उपयोगी होगा, क्योंकि मुझे प्रश्नों में और कुछ उत्तरों या टिप्पणियों में कई अलिखित मान्यताएँ दिखाई देती हैं।
शिफ्टिंग और गुणा के परिणामी सापेक्ष रनटाइम का सी के साथ कोई लेना-देना नहीं है। जब मैं सी कहता हूं, तो मेरा मतलब किसी विशिष्ट कार्यान्वयन का उदाहरण नहीं है, जैसे कि जीसीसी का वह संस्करण या संस्करण, लेकिन भाषा। मेरा मतलब यह नहीं है कि यह विज्ञापन अनुपस्थित है, लेकिन उदाहरण के लिए एक चरम उदाहरण का उपयोग करने के लिए: आप सी मानकों का पूरी तरह से मानकों को लागू कर सकते हैं और गुणा करने में एक घंटे का समय लग सकता है, जबकि शिफ्टिंग में मिलीसेकंड - या दूसरे स्थान पर ले जाता है। मुझे C या C ++ में ऐसे किसी भी प्रदर्शन प्रतिबंध के बारे में पता नहीं है।
आप तर्क में इस तकनीकी की परवाह नहीं कर सकते हैं। आपका इरादा शायद केवल पारियों और गुणा करने के सापेक्ष प्रदर्शन का परीक्षण करना था और आपने सी को चुना, क्योंकि इसे आम तौर पर एक निम्न स्तर की प्रोग्रामिंग भाषा के रूप में माना जाता है, इसलिए कोई अपने स्रोत कोड को सीधे अधिक निर्देशों में अनुवाद करने की उम्मीद कर सकता है। इस तरह के प्रश्न बहुत आम हैं और मुझे लगता है कि एक अच्छे उत्तर को इंगित करना चाहिए कि सी में भी आपका स्रोत कोड सीधे निर्देशों में अनुवाद नहीं करता है जैसा कि आप दिए गए उदाहरण में सोच सकते हैं। मैंने आपको नीचे कुछ संभावित संकलन परिणाम दिए हैं।
यह वह जगह है जहां वास्तविक दुनिया के सॉफ्टवेयर में इस समानता को प्रतिस्थापित करने की उपयोगिता पर सवाल खड़े होते हैं। आप अपने प्रश्न में टिप्पणियों में कुछ देख सकते हैं, जैसे कि एरिक लिपर्ट। यह ऐसी प्रतिक्रिया के अनुरूप है जो आप आमतौर पर ऐसे अनुकूलन के जवाब में अधिक अनुभवी इंजीनियरों से प्राप्त करेंगे। यदि आप उत्पादन कोड में बाइनरी पारियों का उपयोग कई गुना और विभाजन के एक कंबल साधन के रूप में करते हैं, तो लोग आपके कोड में सबसे अधिक संभावना करेंगे और कुछ हद तक भावनात्मक प्रतिक्रिया होगी ("मैंने स्वर्ग के लिए जावास्क्रिप्ट के बारे में किए गए इस निरर्थक दावे को सुना है")। यह नौसिखिए प्रोग्रामर के लिए कोई मतलब नहीं हो सकता है, जब तक कि वे उन प्रतिक्रियाओं के कारणों को बेहतर ढंग से नहीं समझते हैं।
वे कारण मुख्य रूप से इस तरह के अनुकूलन की घटी हुई पठनीयता और निरर्थकता का एक संयोजन है, जैसा कि आपको उनके सापेक्ष प्रदर्शन की तुलना करने से पहले ही पता चल गया होगा। हालांकि, मुझे नहीं लगता है कि लोगों की प्रतिक्रिया के रूप में मजबूत होगा यदि गुणा के लिए बदलाव का प्रतिस्थापन इस तरह के अनुकूलन का एकमात्र उदाहरण था। आपके जैसे प्रश्न अक्सर विभिन्न रूपों में और विभिन्न संदर्भों में सामने आते हैं। मुझे लगता है कि अधिक वरिष्ठ इंजीनियर वास्तव में इतनी दृढ़ता से प्रतिक्रिया करते हैं, कम से कम मेरे पास कई बार है, यह है कि जब लोग इस तरह के माइक्रो-ऑप्टिमाइज़ेशन को कोड आधार पर उदारतापूर्वक नियोजित करते हैं, तो बहुत अधिक नुकसान की संभावना है। यदि आप एक बड़े कोड आधार पर Microsoft जैसी कंपनी में काम करते हैं, तो आप अन्य इंजीनियरों के स्रोत कोड को पढ़ने में बहुत समय बिताएंगे, या उसमें कुछ कोड खोजने का प्रयास करेंगे। यह आपका अपना कोड भी हो सकता है कि आप कुछ वर्षों के समय में, विशेष रूप से कुछ सबसे अधिक समय पर, जैसे कि जब आपको पेजर पर आपको कॉल मिल रहा हो, एक प्रोडक्शन आउटेज को ठीक करना होगा। शुक्रवार की रात को ड्यूटी, दोस्तों के साथ मस्ती की एक रात के लिए बाहर जाने के लिए ... यदि आप कोड पढ़ने में इतना समय बिताते हैं, तो आप इसे यथासंभव पठनीय होने की सराहना करेंगे। अपने पसंदीदा उपन्यास को पढ़ने की कल्पना करें, लेकिन प्रकाशक ने एक नया संस्करण जारी करने का फैसला किया है, जहां वे एब्बर का उपयोग करते हैं। सभी ovr th plc bcs तेरा thnk यह svs spc। यह प्रतिक्रिया के समान है कि अन्य इंजीनियरों को आपके कोड में होना चाहिए, यदि आप उन्हें इस तरह के अनुकूलन के साथ छिड़कते हैं। जैसा कि अन्य जवाबों में कहा गया है, यह स्पष्ट करना बेहतर है कि आपका क्या मतलब है,
हालांकि उन वातावरणों में भी, आप अपने आप को एक साक्षात्कार प्रश्न हल कर सकते हैं, जहाँ आपसे यह जानने की अपेक्षा की जाती है या कुछ अन्य समानता। उन्हें जानना बुरा नहीं है और एक अच्छा इंजीनियर बाइनरी शिफ्टिंग के अंकगणितीय प्रभाव से अवगत होगा। ध्यान दें कि मैंने यह नहीं कहा कि यह एक अच्छा इंजीनियर बनाता है, लेकिन यह कि एक अच्छा इंजीनियर जानता होगा, मेरी राय में। विशेष रूप से, आप अभी भी कुछ प्रबंधक पा सकते हैं, आमतौर पर आपके साक्षात्कार लूप के अंत की ओर, जो आपको कोडिंग प्रश्न में इस स्मार्ट इंजीनियरिंग "चाल" को प्रकट करने की खुशी की प्रत्याशा में व्यापक रूप से मुस्कुराएगा। , भी, इस्तेमाल किया जा रहा है या प्रेमी इंजीनियरों में से एक है और "सिर्फ" एक प्रबंधक नहीं है। उन स्थितियों में, बस प्रभावित दिखने की कोशिश करें और उन्हें ज्ञानवर्धक साक्षात्कार के लिए धन्यवाद दें।
आपने C में गति अंतर क्यों नहीं देखा? सबसे संभावित उत्तर यह है कि यह दोनों एक ही विधानसभा कोड के परिणामस्वरूप थे:
int shift(int i) { return i << 2; }
int multiply(int i) { return i * 2; }
दोनों में संकलित कर सकते हैं
shift(int):
lea eax, [0+rdi*4]
ret
अनुकूलन के बिना GCC पर, अर्थात "-O0" ध्वज का उपयोग करके, आपको यह मिल सकता है:
shift(int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov eax, DWORD PTR [rbp-4]
sal eax, 2
pop rbp
ret
multiply(int):
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], edi
mov eax, DWORD PTR [rbp-4]
add eax, eax
pop rbp
ret
जैसा कि आप देख सकते हैं, "-O0" को GCC में पास करने का मतलब यह नहीं है कि यह कुछ स्मार्ट नहीं होगा कि यह किस तरह का कोड बनाता है। विशेष रूप से, ध्यान दें कि इस मामले में भी कंपाइलर एक बहु-निर्देश के उपयोग से बचता है। आप अन्य संख्याओं द्वारा बदलाव के साथ एक ही प्रयोग को दोहरा सकते हैं और यहां तक कि संख्याओं को गुणा कर सकते हैं जो दो की शक्तियां नहीं हैं। संभावना है कि आपके मंच पर आपको बदलाव और परिवर्धन का एक संयोजन दिखाई देगा, लेकिन कोई गुणा नहीं। ऐसा लगता है कि संकलक के लिए संयोग की एक बिट के रूप में स्पष्ट रूप से उन सभी मामलों में गुणा का उपयोग करने से बचें यदि गुणा और पारियों में वास्तव में एक ही लागत थी, तो क्या ऐसा नहीं होता है? लेकिन मेरा मतलब सबूत के लिए आपूर्ति की आपूर्ति से नहीं है, इसलिए हमें आगे बढ़ना चाहिए।
आप उपरोक्त कोड के साथ अपना परीक्षण फिर से शुरू कर सकते हैं और देख सकते हैं कि क्या आपको गति में अंतर दिखाई देता है। तब भी आप शिफ्ट बनाम मल्टीप्ल का परीक्षण नहीं कर रहे हैं, जैसा कि आप गुणा के अभाव से देख सकते हैं, हालाँकि, लेकिन कोड के बदलाव के लिए जीसीसी द्वारा झंडे के एक निश्चित सेट के साथ उत्पन्न कोड और किसी विशेष उदाहरण में गुणा किया गया था । इसलिए, एक अन्य परीक्षण में आप विधानसभा कोड को हाथ से संपादित कर सकते हैं और इसके बजाय "गुणा" विधि के लिए कोड में "इमुल" निर्देश का उपयोग कर सकते हैं।
यदि आप संकलक के उन स्मार्टों में से कुछ को पराजित करना चाहते हैं, तो आप अधिक सामान्य पारी और गुणा पद्धति को परिभाषित कर सकते हैं और कुछ इस तरह से समाप्त करेंगे:
int shift(int i, int j) { return i << j; }
int multiply(int i, int j) { return i * j; }
निम्नलिखित विधानसभा कोड प्राप्त कर सकते हैं:
shift(int, int):
mov eax, edi
mov ecx, esi
sal eax, cl
ret
multiply(int, int):
mov eax, edi
imul eax, esi
ret
यहां हमारे पास अंततः GCC 4.9 के उच्चतम अनुकूलन स्तर पर भी है, विधानसभा निर्देशों में वह अभिव्यक्ति जो आपने उम्मीद की होगी जब आप शुरू में अपने परीक्षण के लिए निर्धारित करेंगे। मुझे लगता है कि प्रदर्शन अनुकूलन में एक महत्वपूर्ण सबक हो सकता है। हम अपने कोड में ठोस स्थिरांक के लिए चर को प्रतिस्थापित करने के लिए किए गए अंतर को देख सकते हैं, स्मार्टरों के संदर्भ में जो कंपाइलर लागू करने में सक्षम है। माइक्रो-ऑप्टिमाइज़ेशन जैसे शिफ्ट-मल्टीली प्रतिस्थापन कुछ बहुत ही निम्न-स्तरीय अनुकूलन हैं जो एक कंपाइलर आमतौर पर आसानी से कर सकता है। अन्य अनुकूलन जो प्रदर्शन पर बहुत अधिक प्रभाव डालते हैं , उन्हें कोड के इरादे की समझ की आवश्यकता होती हैयह अक्सर संकलक द्वारा सुलभ नहीं होता है या केवल कुछ अनुमान द्वारा अनुमान लगाया जा सकता है। यह वह जगह है जहाँ आप एक सॉफ्टवेयर इंजीनियर के रूप में आते हैं और यह निश्चित रूप से पाली के साथ गुणा गुणकों को शामिल नहीं करता है। इसमें ऐसे कारकों को शामिल किया गया है जो एक ऐसी सेवा से बचते हैं जो I / O का उत्पादन करती है और एक प्रक्रिया को अवरुद्ध कर सकती है। यदि आप अपनी हार्ड डिस्क या, भगवान के पास जाते हैं, तो कुछ अतिरिक्त डेटा के लिए एक दूरस्थ डेटाबेस के लिए, जो आपके पास पहले से ही मेमोरी में मौजूद है, जो आपके द्वारा प्रतीक्षा किए जा रहे समय को एक लाख निर्देशों के निष्पादन के लिए खर्च करता है। अब, मुझे लगता है कि हम आपके मूल प्रश्न से थोड़ा दूर भटक गए हैं, लेकिन मुझे लगता है कि यह एक प्रश्नकर्ता को इंगित करता है, खासकर यदि हम किसी ऐसे व्यक्ति को मान लेते हैं जो अभी अनुवाद और कोड के निष्पादन पर समझ हासिल करना शुरू कर रहा है,
तो, कौन सा तेज होगा? मुझे लगता है कि यह एक अच्छा तरीका है जिसे आपने वास्तव में प्रदर्शन अंतर का परीक्षण करने के लिए चुना है। सामान्य तौर पर, कुछ कोड परिवर्तनों के रनटाइम प्रदर्शन से आश्चर्यचकित होना आसान है। आधुनिक तकनीकों को रोजगार देने वाली कई तकनीकें हैं और सॉफ्टवेयर के बीच की बातचीत भी जटिल हो सकती है। यहां तक कि अगर आपको एक स्थिति में एक निश्चित बदलाव के लिए लाभकारी प्रदर्शन परिणाम प्राप्त करना चाहिए, तो मुझे लगता है कि यह निष्कर्ष निकालना खतरनाक है कि इस प्रकार के परिवर्तन से हमेशा प्रदर्शन लाभ मिलेगा। मुझे लगता है कि इस तरह के परीक्षण एक बार चलाना खतरनाक है, "ठीक है, अब मुझे पता है कि कौन सा तेज है!" और फिर अपने माप को दोहराए बिना उत्पादन कोड के लिए उसी अनुकूलन को अंधाधुंध लागू करें।
तो क्या होगा अगर शिफ्ट गुणा से ज्यादा तेज हो? निश्चित रूप से संकेत हैं कि यह सच क्यों होगा। जीसीसी, जैसा कि आप ऊपर देख सकते हैं, लगता है कि (अनुकूलन के बिना भी) प्रतीत होता है कि अन्य निर्देशों के पक्ष में प्रत्यक्ष गुणा से बचना एक अच्छा विचार है। इंटेल 64 और IA-32 आर्किटेक्चर अनुकूलन संदर्भ मैनुअल आप सीपीयू निर्देश के सापेक्ष मूल्य का अनुमान दे देंगे। एक अन्य संसाधन, जो निर्देश विलंबता और थ्रूपुट पर अधिक ध्यान केंद्रित करता है, वह है http://www.agner.org/optimize/instruction_tables.pdf। ध्यान दें कि वे पूर्ण क्रम के अच्छे प्रेडिक्टर नहीं हैं, लेकिन एक दूसरे के सापेक्ष निर्देशों के प्रदर्शन के। एक तंग पाश में, जैसा कि आपका परीक्षण अनुकरण कर रहा है, "थ्रूपुट" का मीट्रिक सबसे अधिक प्रासंगिक होना चाहिए। यह चक्रों की संख्या है जो किसी दिए गए निर्देश को निष्पादित करते समय एक निष्पादन इकाई को आमतौर पर बांधा जाएगा।
तो क्या होगा अगर शिफ्ट गुणा से ज्यादा तेज न हो? जैसा कि मैंने ऊपर कहा, आधुनिक आर्किटेक्चर काफी जटिल हो सकते हैं और शाखा भविष्यवाणी, कैशिंग, पाइपलाइनिंग, और समानांतर निष्पादन इकाइयाँ जैसी चीजें कई बार दो तार्किक समकक्ष कोड के सापेक्ष प्रदर्शन की भविष्यवाणी करना कठिन बना सकती हैं। मैं वास्तव में इस पर जोर देना चाहता हूं, क्योंकि यह वह जगह है जहां मैं इन सवालों के अधिकांश उत्तरों से खुश नहीं हूं और लोगों के शिविर के साथ यह कहते हुए कि यह केवल सच नहीं है (अब) कि स्थानांतरण कई गुना से अधिक तेज है।
नहीं, जहां तक मुझे पता है कि हमने 1970 में या जब भी अचानक गुणन इकाई की लागत के अंतर और बिट शिफ्टर में कुछ गुप्त इंजीनियरिंग सॉस का आविष्कार नहीं किया था। तार्किक गेट्स के संदर्भ में एक सामान्य गुणन, और निश्चित रूप से तार्किक संचालन के संदर्भ में, कई आर्किटेक्चर पर कई परिदृश्यों में बैरल शिफ्टर के साथ एक पारी की तुलना में अभी भी अधिक जटिल है। यह डेस्कटॉप कंप्यूटर पर समग्र रनटाइम में कैसे परिवर्तित होता है, यह थोड़ा अपारदर्शी हो सकता है। मुझे यह पता नहीं है कि वे विशिष्ट प्रोसेसर में कैसे कार्यान्वित किए जाते हैं, लेकिन यहां एक गुणन का विवरण दिया गया है: क्या पूर्णांक गुणन वास्तव में आधुनिक सीपीयू के अलावा एक ही गति है
जबकि यहाँ एक बैरल शिफ्टर की व्याख्या है । पिछले पैराग्राफ में मैंने जिन दस्तावेजों को संदर्भित किया है, वे सीपीयू निर्देशों के प्रॉक्सी द्वारा, संचालन की सापेक्ष लागत पर एक और दृष्टिकोण देते हैं। इंटेल पर इंजीनियरों को अक्सर समान प्रश्न मिलते हैं: इंटेल डेवलपर ज़ोन फ़ोरम पूर्णांक गुणन के लिए घड़ी चक्र और कोर कोर डुअल प्रोसेसर में जोड़
हां, अधिकांश वास्तविक जीवन के परिदृश्यों में, और लगभग निश्चित रूप से जावास्क्रिप्ट में, प्रदर्शन के लिए इस समानता का फायदा उठाने का प्रयास संभवतः एक निरर्थक उपक्रम है। हालाँकि, भले ही हमने गुणन निर्देशों का उपयोग करने के लिए मजबूर किया हो और फिर रन-टाइम में कोई अंतर न देखा हो, जो कि हमारे द्वारा उपयोग की जाने वाली लागत मीट्रिक की प्रकृति के कारण अधिक है, सटीक होने के लिए, और इसलिए नहीं कि लागत में कोई अंतर नहीं है। एंड-टू-एंड रनटाइम एक मीट्रिक है और अगर यह एकमात्र ऐसा है जिसकी हम देखभाल करते हैं, तो सब ठीक है। लेकिन इसका मतलब यह नहीं है कि गुणा और स्थानांतरण के बीच सभी लागत अंतर बस गायब हो गए हैं। और मुझे लगता है कि निश्चित रूप से यह एक अच्छा विचार नहीं है कि उस विचार को एक प्रश्नकर्ता तक पहुंचाया जाए, निहितार्थ या अन्यथा, जो स्पष्ट रूप से बस आधुनिक समय की लागत और लागत में शामिल कारकों का एक विचार प्राप्त करना शुरू कर रहा है। इंजीनियरिंग हमेशा ट्रेड-ऑफ के बारे में होती है। आधुनिक प्रोसेसर जो व्यापार के निष्पादन के समय को प्रदर्शित करने के लिए किए गए हैं, के रूप में जांच और स्पष्टीकरण हम उपयोगकर्ताओं को देखने के रूप में अंत में एक अधिक विभेदित उत्तर दे सकते हैं। और मुझे लगता है कि "यह बस अब और सच नहीं है" की तुलना में अधिक विभेदित उत्तर है, अगर हम सूक्ष्म अनुकूलन अनुकूलित पठनीयता में कम इंजीनियरों की जांच देखना चाहते हैं, क्योंकि यह इस तरह के "अनुकूलन" की प्रकृति के बारे में अधिक सामान्य समझ रखता है। अपने विभिन्न, विविध अवतारों को केवल कुछ विशिष्ट उदाहरणों की तुलना में अलग रखें।