1 <10 तुलना 1 <1000000 से कम महंगा है?


65

मैंने z-indexसीएसएस में गिनती के रूप में सिर्फ ~ 1 बिलियन का उपयोग किया था, और तुलनाओं के बारे में सोच रहा था जो कि जाना चाहिए। क्या बहुत बड़ी संख्या बनाम बहुत छोटे लोगों के बीच तुलना में ALU स्तर पर प्रदर्शन में अंतर है?

उदाहरण के लिए, क्या इन दो स्निपेट में से एक दूसरे की तुलना में अधिक महंगा होगा?

snippet 1

for (int i = 0; i < 10000000; i++){
    if (i < 10000000000000) {
        //do nothing
    }
}

snippet 2

for (int i = 0; i < 10000000; i++){
    if (i < 1000) {
        //do nothing
    }
}


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

18
चूंकि यह सीएसएस में किया जाता है, एक स्ट्रिंग को पूर्णांक में परिवर्तित करना संभवतः समय बिताने के निष्पादन के मामले में तुलना ऑपरेशन पर हावी होगा।

58
अगर आपको CSS फ़ाइल में z-index के रूप में 1000000000 का उपयोग करने की आवश्यकता है, तो आपने कुछ गलत किया है।
बर्गी

6
CSS के लिए, एक पूर्णांक में पाठ को परिवर्तित करने का ओवरहेड परिवर्तित किए जा रहे अंकों की संख्या पर निर्भर करेगा (जहां 6 अंकों की संख्या 1000000 की तरह 1 अंक की तरह 1 अंक के रूप में लगभग 6 गुना महंगी हो सकती है); और यह ओवरहेड पूर्णांक तुलनाओं के ओवरहेड से बड़े परिमाण के आदेश हो सकते हैं।
ब्रेंडन

जवाबों:


82

प्रत्येक प्रोसेसर जो मैंने काम किया है, वह दूसरे से किसी एक ऑपरेंड को घटाकर तुलना करता है, परिणाम को त्यागकर प्रोसेसर के झंडे (शून्य, नकारात्मक, आदि) को अकेला छोड़ देता है। क्योंकि एक ही ऑपरेशन के रूप में घटाव किया जाता है, ऑपरेंड की सामग्री कोई मायने नहीं रखती है।

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

का वर्णन CMP("तुलना") निर्देश 2A, पृष्ठ 3-126, या पीडीएफ के पृष्ठ 618 में है, और इस ऑपरेशन के बारे में बताता है:

temp ← SRC1 − SignExtend(SRC2);
ModifyStatusFlags; (* Modify status flags in the same manner as the SUB instruction*)

इसका मतलब है कि दूसरा ऑपरेंड साइन-एक्सटेंडेड है, यदि आवश्यक हो, पहले ऑपरेंड से घटाया जाए और परिणाम प्रोसेसर में एक अस्थायी क्षेत्र में रखा जाए। फिर स्थिति के झंडे उसी तरह सेट किए जाते हैं जैसे वे SUB("घटाना") निर्देश (पीडीएफ का पृष्ठ 1492) के लिए होगा।

वहाँ में कोई जिक्र नहीं है CMPया SUBप्रलेखन कि ऑपरेंड के मूल्यों विलंबता पर कोई असर नहीं है, तो आप का उपयोग किसी भी मूल्य सुरक्षित है।


5
क्या होगा यदि संख्या 32-बिट अंकगणित के लिए बहुत बड़ी हो जाए? तब यह धीमी गणना के लिए विभाजित नहीं होगा?
फाल्को

3
@ फाल्को 64-बिट ALU के साथ सीपीयू पर नहीं (जो इन दिनों एम्बेडेड स्पेस को छोड़कर सभी में बहुत ज्यादा है।)
रीहैब

8
@ फ़ाल्को: हाँ, लेकिन चूंकि प्रश्न ALU प्रदर्शन के बारे में पूछता है, इसका निहितार्थ यह है कि मान CPU के शब्द आकार या किसी भी SIMD निर्देशों की क्षमताओं में फिट बैठता है। इससे बड़ी संख्या पर परिचालन को सीपीयू के बाहर कई निर्देशों के साथ लागू करना होगा। 30 साल पहले यह बहुत आम था जब आपके पास काम करने के लिए सिर्फ 8- या 16-बिट रजिस्टर थे।
17

6
@ फाल्को को डिबगिंग की आवश्यकता कैसे होगी? यह बग नहीं है; यह सीपीयू पर 64-बिट ऑप्स करना थोड़ा धीमा है जो मूल रूप से 64-बिट ऑप्स का समर्थन नहीं करता है। यह सुझाव देते हुए कि किसी को कभी भी 2 ^ 31-1 से ऊपर की संख्या का उपयोग नहीं करना चाहिए, थोड़ा हास्यास्पद लगता है।
रीहैब

2
@ फ़ाल्को ने कहा है कि, क्या ब्राउज़र में रेंडरिंग इंजन भी z- सूचकांकों का प्रतिनिधित्व करने के लिए पूर्णांक का उपयोग करते हैं? अधिकांश रेंडरिंग इंजन मैं हर चीज के लिए एकल-सटीक फ़्लोट्स के उपयोग से परिचित हूं (अंतिम रेज़राइज़ेशन चरण तक), लेकिन मैंने वास्तव में ब्राउज़र रेंडरिंग इंजनों का अध्ययन नहीं किया है।
14

25

क्या बहुत बड़ी संख्या बनाम बहुत छोटे लोगों के बीच तुलना में ALU स्तर पर प्रदर्शन में अंतर है?

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

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


यह उल्लेख किया जाना चाहिए, कि प्रश्न में प्रस्तावित संख्याएँ एक विशिष्ट 32-बिट पूर्णांक प्रकार में अलग-अलग संख्यात्मक प्रकार की हैं ...
Falco

19

कई प्रोसेसर में "छोटे" निर्देश होते हैं जो कुछ निश्चित-निर्दिष्ट ऑपरेंड पर तुलनात्मक सहित अंकगणितीय ऑपरेशन कर सकते हैं। उन विशेष मानों के अलावा अन्य कार्यों को या तो बड़े अनुदेश प्रारूप का उपयोग करना चाहिए या, कुछ मामलों में, "मेमोरी से लोड मान" निर्देश का उपयोग करना चाहिए। एआरएम कॉर्टेक्स-एम 3 निर्देश सेट में, उदाहरण के लिए, एक मूल्य की तुलना में कम से कम पांच तरीके हो सकते हैं:

    cmp r0,#1      ; One-word instruction, limited to values 0-255

    cmp r0,#1000   ; Two-word instruction, limited to values 0-255 times a power of 2

    cmn r0,#1000   ; Equivalent to comparing value with -1000
                   ; Two-word instruction, limited to values 0-255 times a power of 2

    mov r1,#30000  ; Two words; can handle any value 0-65535
    cmp r0,r1      ; Could use cmn to compare to values -1 to -65535

    ldr r1,[constant1000000] ; One or two words, based upon how nearby the constant is
    cmp r0,r1
    ...

constant1000000:
    dd  1000000

पहला रूप सबसे छोटा है; दूसरा और तीसरा रूप मेमोरी की गति के आधार पर जल्दी या जल्दी निष्पादित नहीं हो सकता है, जिसमें से कोड प्राप्त होता है। चौथा रूप लगभग निश्चित रूप से पहले तीन की तुलना में धीमा होगा, और पांचवां रूप भी धीमा होगा, लेकिन बाद वाले का उपयोग किसी भी 32-बिट मान के साथ किया जा सकता है।

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

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


MIPS पर आप केवल 16-बिट तुरंत कर सकते हैं, इसलिए निश्चित रूप से 1 के साथ तुलना कम होगी और (शायद) 1000000 से अधिक तेज होगी। शायद Sparc और PowerPC के लिए भी ऐसा ही हो। और मुझे लगता है कि मैंने कुछ स्रोतों से पढ़ा है कि इंटेल कई मामलों में छोटे तत्काल पर परिचालन का अनुकूलन करता है लेकिन मैं तुलना करने के लिए निश्चित नहीं हूं या नहीं
phuclv

@ LưuV LnhPhúc: लूप से पहले एक रजिस्टर लोड किया जा सकता है। उस बिंदु पर, वास्तविक तुलना किसी भी मामले में निर्देशों की समान संख्या होगी।
cHao

चूंकि लूप ऑप द्वारा केवल एक उदाहरण था और प्रश्न उदाहरण के लिए एक जेड-इंडेक्स था, यदि आपके पास 1000 ऑब्जेक्ट हैं, प्रत्येक का अपना जेड-इंडेक्स है और आप उन्हें 100000000 ... 1000000999 या 10000 पर सेट करते हैं ... 10999 और आप रेंडर करने से पहले छँटाई के लिए उन पर लूप करते हैं, कई तुलना और कई लोड निर्देश हैं। वहाँ यह एक फर्क कर सकता है!
फाल्को

@ फाल्को: उस मामले में, तुरंत भी कारक नहीं होगा; एक रजिस्टर के खिलाफ लोड करना और तुलना करना बहुत अनिवार्य लगता है।
cHao

@ कोको: यदि कोई एक दूसरे के खिलाफ जेड सूचक की तुलना कर रहा है, तो वे रजिस्टरों में होंगे। यदि कोई अलग-अलग सूचकांकों की कुछ श्रेणियों को संभाल रहा है जो तत्काल तुलना कर सकते हैं। आम तौर पर एक लूप शुरू होने से पहले स्थिरांक लोड हो जाएगा, लेकिन अगर किसी के पास एक लूप था जिसे स्मृति से मानों के जोड़े को पढ़ने की जरूरत थी और प्रत्येक जोड़ी के पहले मूल्य की तुलना पांच अलग-अलग (गैर-समान रूप से अंतर) स्थिरांक 100000 के साथ की जाती है 100499 के लिए, और पांच अन्य ऐसे स्थिरांक के साथ अन्य मूल्य, यह बहुत तेजी से हो सकता है 100250 घटाना (एक रजिस्टर में रखा) और फिर मूल्यों के साथ तुलना -250 से 250 ...
सुपरकैट

5

इस प्रश्न का संक्षिप्त उत्तर है, नहीं , उन संख्याओं के परिमाण के आधार पर दो संख्याओं की तुलना करने के लिए कोई समय अंतर नहीं है , यह मानते हुए कि वे एक ही डेटा प्रकार (जैसे 32-बिट इनट्स या 64-बिट दोनों) में संग्रहीत हैं।

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

केवल ऐसे मामले जो मैं सोच सकता हूं कि मैंने सामना किया है, जहां दो संख्याओं की तुलना एक एकल-चक्र ऑपरेशन नहीं था, निम्नलिखित हैं:

  • निर्देश जहां वास्तव में ऑपरेशंस लाने में एक मेमोरी लेटेंसी है, लेकिन इसका कोई लेना-देना नहीं है कि तुलना खुद कैसे काम करती है (और आमतौर पर RISC आर्किटेक्चर पर संभव नहीं है, हालांकि यह आमतौर पर CISC डिजाइनों पर संभव है, जैसे x86 / x64।
  • आर्किटेक्चर के आधार पर फ्लोटिंग-पॉइंट की तुलना बहु-चक्र हो सकती है।
  • प्रश्न में संख्या ALU के शब्द आकार में फिट नहीं है और इस प्रकार, तुलना को कई निर्देशों में तोड़ दिया जाना चाहिए।

4

@ रॉबर्टहार्इ का उत्तर अच्छा है; इस उत्तर को उसके पूरक मानें।


आपको शाखा भविष्यवाणी पर भी विचार करना चाहिए :

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

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

विषय पर उत्कृष्ट स्टैक ओवरफ्लो प्रश्न


शाखा की भविष्यवाणी शाखा समय को प्रभावित करती है, लेकिन तुलनात्मक समय को ही नहीं।
पुनर्वसु

3

यह कार्यान्वयन पर निर्भर करता है, लेकिन यह बहुत, बहुत संभावना नहीं है

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

कंप्यूटर के दृष्टिकोण से, सभी डबल्स समान मात्रा में डेटा ले जाते हैं: 64 बिट्स, चाहे मूल्य 1 या -3.14 या 1000000 या 1e100 हो । इन नंबरों पर एक ऑपरेशन करने में जितना समय लगता है, वह उन नंबरों के वास्तविक मूल्य पर निर्भर नहीं करता है, क्योंकि यह हमेशा डेटा की एक ही राशि पर काम कर रहा है। चीजों को इस तरह से करने में एक ट्रेडऑफ है, जिसमें डबल्स सभी नंबरों (या उनकी सीमा के भीतर भी सभी नंबरों) का सही प्रतिनिधित्व नहीं कर सकते हैं, लेकिन वे ज्यादातर मामलों के लिए पर्याप्त रूप से पास हो सकते हैं, और सीएसएस के प्रकार संख्यात्मक रूप से नहीं हैं। -उसकी तुलना में अधिक सटीकता की आवश्यकता के लिए पर्याप्त मात्रा में। जावास्क्रिप्ट के साथ सीधे-समग्र संगतता के लाभों के साथ इसे मिलाएं, और आपको युगल के लिए बहुत मजबूत मामला मिला है।

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

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


0

यदि इस कोड को हर बार चलाने के दौरान व्याख्या की जा रही थी, तो एक अंतर होगा क्योंकि इसकी 10000000000000तुलना में टोकन और व्याख्या में अधिक समय लगता है 1000। हालांकि, इस मामले में दुभाषियों का यह पहला पहला अनुकूलन है: एक बार टोकन लेना और टोकन की व्याख्या करना।

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