2010-09-07 8 views
16

सी # के बीच> 0 और> = 1 जो तेज़ और बेहतर है?सी # के बीच> 0 और> = 1 जो तेज़ और बेहतर है?

+9

पेडेंट यहां। मुझे लगता है कि आप पूर्णांक के लिए मतलब है। फ्लोट्स के लिए, यह वही बात नहीं है: पी –

+43

'> 0' तेज है क्योंकि यह टाइप करने के लिए एक कम चरित्र है। – RedFilter

+0

@FedFilter और तेज़ बेहतर है ... – kenny

उत्तर

12

परिभाषित नहीं किया गया। आप स्पष्ट रूप से सी # के लिए पूछते हैं - लेकिन यह ऐसा कुछ है जो प्रोसेसर आर्किटेक्चर पर निर्भर करता है, यानी सीएलआर रनटाइम कंपाइलर।

+1

मुझे लगता है कि यह हर प्रोग्रामिंग भाषा के बारे में सच है। – Andy

+0

... और बेहतर क्या है इसका उपयोग उस संदर्भ में अधिक पठनीय है जो इसका उपयोग किया जाता है। पठनीयता –

44

न तो; यदि दोनों तेज या बेहतर हैं तो दोनों को एक ही चीज़ पर संकलित करना चाहिए।

अधिक महत्वपूर्ण बात यह है कि अधिकतर प्रोग्रामर शायद > 0 अधिक पठनीय पाएंगे, और इस तरह के उप माइक्रो अनुकूलन की तुलना में पठनीयता अधिक महत्वपूर्ण है।

+7

+1 मुझे आपके पठनीयता के बारे में पता नहीं है; मैंने पढ़ा है> = 1 "1 या अधिक" के रूप में, और यह "शून्य से अधिक" की तुलना में किसी शर्त को परिभाषित करने का एक और प्राकृतिक तरीका है। हालांकि, "पांच से अधिक" वार्तालाप में सही समझ में आता है। मुझे लगता है कि पठनीयता संदर्भ पर निर्भर करेगी, और किसी भी आवश्यकता दस्तावेज या उपयोगकर्ता गाइड की उपस्थिति और शब्द जो डेवलपर कोड के समानांतर में देख रहे होंगे। यह भी शामिल गणित के प्रकार पर निर्भर करता है; जैसा कि जेसी मिलिकन ने कहा था, दो तुलना फ्लोटिंग-पॉइंट दुनिया में बराबर नहीं होगी। – Matt

+7

के महत्व को इंगित करने के लिए – KeithS

+0

@ किथ्स: मैंने '> 0' के इरादे को" सकारात्मक nonzero पूर्णांक "के रूप में पढ़ा। पढ़ना '> = 1' मुझे इस बारे में सोचना पड़ता है कि कैसे तय करने के लिए पूर्णांक के दशमलव के सही अंक नहीं हैं। और हाँ, अभिव्यक्ति समान नहीं हैं; हालांकि मैंने पहले व्यापक फ़्लोटिंग पॉइंट प्रोग्राम नहीं किए हैं। क्या ऐसे मामले हैं जहां '> = 1' बेहतर होगा? ज़रूर। लेकिन प्रश्न के लिखित तरीके को देखते हुए मैंने "सकारात्मक nonzero पूर्णांक" इरादा माना था। –

7

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

ध्यान रखें, हालांकि, प्रदर्शन के अनुसार यह चरम सूक्ष्म अनुकूलन सबसे अधिक अनचाहे है।

बेहतर विकल्प होने वाला है जो कभी भी अधिक पठनीय है और आपके इरादे को आपके कोड में सबसे अच्छा बताता है।

1

तेजी से उत्तर देने के लिए, मुझे यकीन नहीं है, लेकिन मुझे लगता है कि वे बराबर हैं। और बेहतर के लिए उत्तर देने के लिए, मुझे लगता है कि यह संदर्भ पर निर्भर करता है।

0

आपको तब तक कोई फर्क नहीं पड़ता जब तक कि संभवतः एक बहुत ही तंग लूप में जो आपके आवेदन में महत्वपूर्ण प्रदर्शन नहीं करता है। फिर आपको यह तय करने के लिए कि कौन सा बेहतर है, आपको अपना कोड प्रोफाइल करना होगा।

उस व्यक्ति का उपयोग करें जो आपके आवेदन में सबसे अधिक समझ में आता है।

26

वह बेहतर है जो सबसे स्पष्ट रूप से आपके इरादे को व्यक्त करता है।

आप अगर एक पूर्णांक में रेंज है देखने के लिए परीक्षण कर रहे हैं [1, 6] तो आप इसे लिखना चाहिए के रूप में:

if (x >= 1 && x <= 6) { ... } 

लेखन यह काम होगा, लेकिन इतना स्पष्ट विनिर्देश को पूरा नहीं करता :

if (x > 0 && x < 7) { ... } 

मैं यह भी मान रहा हूं कि आप यहां पूर्णांक प्रकारों के बारे में बात कर रहे हैं। यदि आप फ़्लोटिंग पॉइंट या दशमलव नंबर से निपट रहे हैं तो वे बराबर नहीं हैं।


जब तक आप अपने कोड प्रोफाइल और इस पाया टोंटी होने के लिए है, तो आप सूक्ष्म अनुकूलन के बारे में चिंता नहीं करनी चाहिए। यहां तक ​​कि प्रत्येक मामले में सी # कंपाइलर द्वारा उत्पन्न कोड का निरीक्षण करना दिलचस्प हो सकता है यह देखने के लिए कि क्या वे एक ही आईएल में संकलित हैं या नहीं। यह .NET Reflector का उपयोग करके किया जा सकता है।में

if (x >= 1) 
{ 
    Console.WriteLine("True!"); 
} 

परिणाम:

L_000b: ldloc.0   // Load the value of x 
L_000c: ldc.i4.1   // Load the constant 1 
L_000d: blt.s L_0019  // Branch if less than 
L_000f: ldstr "True!" 
L_0014: call void [mscorlib]System.Console::WriteLine(string) 

जबकि:

निम्नलिखित आईएल में
if (x > 0) 
{ 
    Console.WriteLine("True!"); 
} 

परिणाम:

L_000b: ldloc.0   // Load the value of x 
L_000c: ldc.i4.0   // Load the constant 0 
L_000d: ble.s L_0019  // Branch if less than or equal 
L_000f: ldstr "True!" 
L_0014: call void [mscorlib]System.Console::WriteLine(string) 

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

यह देखते हुए कि वे एक ही आईएल को संकलित नहीं करते हैं, यह देखने का सबसे अच्छा तरीका है कि वास्तव में एक लूप में कोड चलाने के लिए और प्रत्येक संस्करण को निष्पादित करने में कितना समय लगता है। मैंने ऐसा करने की कोशिश की लेकिन मुझे कोड लिखने के दो तरीकों के बीच कोई मापनीय प्रदर्शन अंतर नहीं मिला।

+0

मैं सहमत हूं! यह कथन की अपेक्षा की जाती है ...> 0 और> = 1 वास्तव में 2 अलग-अलग (और कभी-कभी समान) चीजें करता है ... आप इसे या तो इसके सभी भाग या इसके हिस्से से चाहते हैं! –

+0

मुझे यह पसंद है कि आपने आईएल दिखाया है, खासकर जब यह बाइटकोड में तुलना स्विच करता है। – Nick

0

तो आमतौर पर जब मैं कुछ> 0 या> = 1 से तुलना करता हूं, तो मैं यह देखने की कोशिश कर रहा हूं कि कोई सरणी/संग्रह में कोई तत्व है या नहीं। यदि ऐसा है, तो .Count > 0 का उपयोग करने के बजाय, में Enumerable.Any() का उपयोग करने का प्रयास करें जो बहुत तेज़ होना चाहिए।

अन्यथा, मैं नहीं जानता कि :)

+0

'कोई भी()' तेज क्यों होगा? मुझे लगता है कि यह धीमा होगा, क्योंकि 'गणना' केवल एक संपत्ति एक्सेसर है, लेकिन 'किसी भी()' को अनुक्रम की पहली अवधि का आकलन करना है। – jnylen

+0

@jnylen: आप जिस गिनती का उपयोग कर रहे हैं उस पर निर्भर करता है। 'संख्यात्मक। गणना()' 'umerable.Any() 'से भी बदतर है। यदि आपके कंटेनर में 'गणना' संपत्ति है (यानी 'सूची') तो हाँ, आपको इसका उपयोग करना चाहिए। –

+2

मुझे लगता है .एनी() का मूल्यांकन करता है। गणना> 0 अगर संग्रह उस सदस्य का समर्थन करता है। और यह हमेशा से तेज है। गणना() जब संग्रह इसका समर्थन नहीं करता है। यह सुनिश्चित नहीं है कि यह किस आईएल को संकलित करता है, इसलिए यह बहुत मदद नहीं हो सकता है ... –

2

कोई अंतर नहीं है क्योंकि cpu आंतरिक रूप से दो नंबर की एक घटाव करता है और परिणाम और अतिप्रवाह का निरीक्षण नहीं है। निर्देश के लिए कोई अतिरिक्त कदम शामिल नहीं है।

जब कोड की बात आती है तो यह उस दस्तावेज़ पर निर्भर करता है जिसे आप दस्तावेज़ बनाने का प्रयास कर रहे हैं। > = 1 का मतलब है कि 1 सबसे कम संभव संख्या है। > 0 का मतलब है कि 0 की अनुमति नहीं है। एक छोटा अर्थपूर्ण अंतर है कि पेशेवरों को नोटिस होगा। वे अपने इरादे को दस्तावेज करने के लिए सही ऑपरेटर का चयन करेंगे।

आपको लगता है कि> = n और> = n + 1 ही आप गलत कर रहे हैं कर रहे हैं:> = int.MaxValue और> (int.MaxValue +1) अलग हैं ^^

3

मैं सहमत अन्य प्रतिक्रियाएं कि सूक्ष्म अनुकूलन को आमतौर पर ध्यान में नहीं रखा जाना चाहिए। हालांकि यह देखना दिलचस्प हो सकता है कि दोनों संस्करणों में से कौन सा छोटा/स्पष्ट रूप से_फास्टर आईएल है।

तो:

(डीबग)

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    .maxstack 2 
    .locals init (
     [0] int32 i, 
     [1] bool CS$4$0000) 
    L_0000: nop 
    L_0001: ldc.i4.3 
    L_0002: stloc.0 
    L_0003: ldloc.0 
    L_0004: ldc.i4.0 
    L_0005: cgt 
    L_0007: ldc.i4.0 
    L_0008: ceq 
    L_000a: stloc.1 
    L_000b: ldloc.1 
    L_000c: brtrue.s L_001b 
    L_000e: nop 
    L_000f: ldstr "i is greater than zero" 
    L_0014: call void [mscorlib]System.Console::Write(string) 
    L_0019: nop 
    L_001a: nop 
    L_001b: ret 
} 

(जारी)

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    .maxstack 2 
    .locals init (
     [0] int32 i) 
    L_0000: ldc.i4.3 
    L_0001: stloc.0 
    L_0002: ldloc.0 
    L_0003: ldc.i4.0 
    L_0004: ble.s L_0010 
    L_0006: ldstr "i is greater than zero" 
    L_000b: call void [mscorlib]System.Console::Write(string) 
    L_0010: ret 
} 

जबकि

:

using System; 

namespace IL_Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int i = 3; 
      if (i > 0) 
      { 
       Console.Write("i is greater than zero"); 
      } 
     } 
    } 
} 

में तब्दील

using System; 

namespace IL_Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int i = 3; 
      if (i >= 1) 
      { 
       Console.Write("i is greater than zero"); 
      } 
     } 
    } 
} 
में

(डीबग)

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    .maxstack 2 
    .locals init (
     [0] int32 i, 
     [1] bool CS$4$0000) 
    L_0000: nop 
    L_0001: ldc.i4.3 
    L_0002: stloc.0 
    L_0003: ldloc.0 
    L_0004: ldc.i4.1 
    L_0005: clt 
    L_0007: stloc.1 
    L_0008: ldloc.1 
    L_0009: brtrue.s L_0018 
    L_000b: nop 
    L_000c: ldstr "i is greater than zero" 
    L_0011: call void [mscorlib]System.Console::Write(string) 
    L_0016: nop 
    L_0017: nop 
    L_0018: ret 
} 

(जारी)

.method private hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    .maxstack 2 
    .locals init (
     [0] int32 i) 
    L_0000: ldc.i4.3 
    L_0001: stloc.0 
    L_0002: ldloc.0 
    L_0003: ldc.i4.1 
    L_0004: blt.s L_0010 
    L_0006: ldstr "i is greater than zero" 
    L_000b: call void [mscorlib]System.Console::Write(string) 
    L_0010: ret 
} 

जहां तक ​​मेरा मैं> = 1 मामूली तेजी से होता है देख सकते हैं i> 0 में से डेबग मोड

रिलीज मोड अल में एल दुविधा एक बीएलई बनाम बीएलटी ऑफ़सेट 0004 पर है। मुझे लगता है कि इन दो आईएल ऑप्स समान रूप से सीपीयू उपभोग करने वाले देशी ओप्स में अनुवाद करते हैं ..

+0

क्या वे स्वैप हैं या क्या मुझे कुछ याद आती है? –

+2

आप कहते हैं कि एक मामूली तेज़ है - आपने अपने बेंचमार्क परिणामों को क्यों पोस्ट नहीं किया? आपने किस मशीन पर परीक्षण किया? अनुकूलन पर? अनुकूलन जेआईटी द्वारा किया जाता है, सी # कंपाइलर द्वारा नहीं, इसलिए उत्पन्न आईएल को देखते हुए प्रदर्शन के बारे में ज्यादा कुछ नहीं लगता है। – Niki

+2

@ कैस्पर: पहला वाला कर रहा है: 'अगर (i> 0) == false', तो वापस लौटें (console.write नहीं)। दूसरा कर रहा है: 'अगर (i <1) == सत्य', तो वापस आओ। आंद्रेई के परीक्षण द्वारा उत्पादित आईएल मार्क बेयर्स के मुकाबले बहुत अधिक वर्बोज़ लगता है। दूसरों द्वारा बनाई गई प्वाइंट: इसे चलाएं, इसे बेंचमार्क करें, पूछें कि यह वास्तव में धीमी है? यहां कोड डिबग संकलित हो सकता है, या कंपाइलर के दूसरे संस्करण के साथ .. हम नहीं जानते। हां, जेआईटी अधिक अनुकूलित कर सकता है या नहीं। बेंचमार्क .. – maxwellb

4

बेशक, यह सीपीयू आर्किटेक्चर पर निर्भर करता है कि आपका प्रोग्राम चालू होगा। X86 पर jge और jg निर्देश, जो यहां प्रासंगिक हैं, चक्र IIRC की समान संख्या लें। 0 के लिए परीक्षण के विशिष्ट मामले में, यदि आप बिना हस्ताक्षर किए गए पूर्णांक का उपयोग कर रहे हैं तो यह cmp के बजाय test निर्देश का उपयोग करने के लिए तेज़ी से हो सकता है, क्योंकि हस्ताक्षर किए गए पूर्णांक> 0 के बराबर है! = 0 अन्य वास्तुकला अलग हो सकते हैं। मुद्दा यह है कि यह इतना निम्न स्तर है कि दुर्लभ मामले में भी यह अनुकूलन के लायक है, इसे अनुकूलित करने के लिए कोई हार्डवेयर-स्वतंत्र तरीका नहीं है।

संपादित करें: उल्लेख करने के लिए भूल गए: किसी भी कंपाइलर या उसके नमक के वीएम को यह पता लगाने में सक्षम होना चाहिए कि परीक्षण> = 1 परीक्षण> 0 के बराबर है और यदि यह असेंबली भाषा में भी अंतर डालता है तो यह एक छोटा सा अनुकूलन करता है स्तर।

0

यदि दोनों के बीच कोई अंतर होगा, तो मैं कहूंगा कि यह ऐसा माइक्रो-ऑप्टिमाइज़ेशन होगा, जो एप्लिकेशन के समग्र प्रदर्शन को प्रभावित नहीं करेगा।

इसके अलावा, जब कोई वास्तव में यह पता लगा रहा है कि उसे> 0 या> = 1 का उपयोग करना है, तो मैं कहूंगा कि कौन सा तेज़ है, यह अनुमान लगाने के लिए लागत (न्यूनतम) प्रदर्शन लाभ से अधिक नहीं है।

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

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