2010-03-23 19 views
5

की तुलना में मैं सी # की गति के बारे में चिंतित था जब यह भारी गणना से संबंधित है, जब आपको कच्ची सीपीयू पावर का उपयोग करने की आवश्यकता होती है।सी ++ और सी # गति

मैंने हमेशा सोचा कि गणना के समय सी ++ सी # से बहुत तेज है। तो मैंने कुछ त्वरित परीक्षण किए। पहला परीक्षण प्राइम संख्या < एक पूर्णांक एन की गणना करता है, दूसरा परीक्षण कुछ पैंडिजिटल संख्याओं की गणना करता है। दूसरे टेस्ट के लिए विचार यहाँ से आता है: Pandigital Numbers

सी # प्रधानमंत्री गणना:

using System; 
using System.Diagnostics; 

class Program 
{ 

    static int primes(int n) 
    { 

     uint i, j; 
     int countprimes = 0; 

     for (i = 1; i <= n; i++) 
     { 
      bool isprime = true; 

      for (j = 2; j <= Math.Sqrt(i); j++) 

       if ((i % j) == 0) 
       { 
        isprime = false; 
        break; 
       } 

      if (isprime) countprimes++; 
     } 

     return countprimes; 
    } 



    static void Main(string[] args) 
    { 
     int n = int.Parse(Console.ReadLine()); 
     Stopwatch sw = new Stopwatch(); 

     sw.Start(); 
     int res = primes(n); 
     sw.Stop(); 
     Console.WriteLine("I found {0} prime numbers between 0 and {1} in {2} msecs.", res, n, sw.ElapsedMilliseconds); 
     Console.ReadKey(); 
    } 
} 

सी ++ संस्करण:

#include <iostream> 
#include <ctime> 
#include <cmath> 

int primes(unsigned long n) { 
unsigned long i, j; 
int countprimes = 0; 
    for(i = 1; i <= n; i++) { 
     int isprime = 1; 
     for(j = 2; j < sqrt((float)i); j++) 
      if(!(i%j)) { 
     isprime = 0; 
     break; 
    } 
    countprimes+= isprime; 
    } 
    return countprimes; 
} 

int main() { 
int n, res; 
cin>>n; 
unsigned int start = clock(); 

res = primes(n); 
int tprime = clock() - start; 
cout<<"\nI found "<<res<<" prime numbers between 1 and "<<n<<" in "<<tprime<<" msecs."; 
return 0; 
} 

जब मैं अभाज्य संख्या < 100,000 से खोजने की कोशिश कर परीक्षण भाग गया, सी # संस्करण 0.614 सेकंड में 0.40 9 सेकेंड और सी ++ संस्करण में समाप्त हुआ। जब मैंने उन्हें 1,000,000 सी # के लिए 6.039 सेकेंड में समाप्त किया और सी ++ लगभग 12.987 सेकेंड में चलाया। सी # में

Pandigital परीक्षण: C++

using System; 
using System.Diagnostics; 

class Program 
{ 
    static bool IsPandigital(int n) 
    { 
     int digits = 0; int count = 0; int tmp; 

     for (; n > 0; n /= 10, ++count) 
     { 
      if ((tmp = digits) == (digits |= 1 << (n - ((n/10) * 10) - 1))) 
       return false; 
     } 

     return digits == (1 << count) - 1; 
    } 

    static void Main() 
    { 
     int pans = 0; 
     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 

     for (int i = 1; i <= 123456789; i++) 
     { 
      if (IsPandigital(i)) 
      { 
       pans++; 
      } 
     } 
     sw.Stop(); 
     Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds); 
     Console.ReadKey(); 
    } 
} 

Pandigital परीक्षण:

#include <iostream> 
#include <ctime> 

using namespace std; 

int IsPandigital(int n) 
    { 
     int digits = 0; int count = 0; int tmp; 

     for (; n > 0; n /= 10, ++count) 
     { 
      if ((tmp = digits) == (digits |= 1 << (n - ((n/10) * 10) - 1))) 
       return 0; 
     } 

     return digits == (1 << count) - 1; 
    } 


int main() { 
    int pans = 0; 
    unsigned int start = clock(); 

    for (int i = 1; i <= 123456789; i++) 
    { 
     if (IsPandigital(i)) 
     { 
     pans++; 
     } 
    } 
    int ptime = clock() - start; 
    cout<<"\nPans:"<<pans<<" time:"<<ptime; 
    return 0; 
} 

सी # संस्करण सी ++ 36.298 सेकंड में 29.906 सेकंड में चलाता है और।

मैंने किसी भी कंपाइलर स्विच को स्पर्श नहीं किया और दोनों सी # और सी ++ प्रोग्राम डीबग विकल्पों के साथ संकलित किए गए। मैंने परीक्षण चलाने का प्रयास करने से पहले मुझे चिंता थी कि सी # सी ++ के पीछे अच्छी तरह से पीछे हट जाएगा, लेकिन अब ऐसा लगता है कि सी # पक्ष में एक बहुत बड़ी गति अंतर है।

क्या कोई इसे समझा सकता है? सी # जलाया गया है और सी ++ मूल संकलित है इसलिए यह सामान्य है कि सी ++ सी # संस्करण से तेज होगा।

उत्तर के लिए धन्यवाद!

मैंने रिलीज कॉन्फ़िगरेशन के लिए सभी परीक्षणों को रेडिड किया है।

पहला परीक्षण (रूढ़ अंक)

सी # (संख्या < 100,0000): 0.189 सेकंड सी ++ (संख्या < 100,0000): 0.036 सेकंड

सी # (nummbers < 1,000,000): 5.300 सेकंड सी ++ (nummbers < 1,000,000): 1.166 सेकंड

दूसरे टेस्ट (Pandigital संख्या):

सी #: 21। 224 सेकंड सी ++: 4.104 सेकंड

तो, सबकुछ बदल गया है, अब सी ++ बहुत तेज है। मेरी गलती यह है कि मैंने डीबग कॉन्फ़िगरेशन के लिए परीक्षण चलाया है। क्या मैं कुछ गति सुधार देख सकता हूं यदि मैं सी # निष्पादन योग्यों को ngen के माध्यम से चलाता हूं?

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

तो, मैं मैं नए करेंगे संभालने हूँ जाएगा हमेशा के लिए इस सवाल का Tough question on WPF, Win32, MFC साथ अटक सकता है, और मैं एक उपयुक्त एपीआई पाते हैं।

+5

"क्या कोई इसे समझा सकता है? सी # जलाया गया है और सी ++ मूल संकलित है इसलिए यह सामान्य है कि सी ++ सी # संस्करण से तेज होगा।" <- डीबग मोड के तहत नहीं। –

+6

"... सी ++ प्रोग्राम डीबग विकल्पों के साथ संकलित किए गए थे।" तो फिर हम प्रदर्शन के बारे में चिंता क्यों कर रहे हैं? – GManNickG

+4

'= 2; जे <(i^(1/2)); जे ++) 'यह कोड गलत है। आप थोड़ा सा कर रहे हैं - या, एक एक्सपोनिएशन नहीं। –

उत्तर

8

तुम क्यों ग्रहण करेंगे कि jitted कोड मूल कोड की तुलना में धीमी है? एकमात्र गति जुर्माना वास्तविक जिंग होगा, जो केवल एक बार होता है (आमतौर पर बोल रहा है)। 30-सेकंड के चलने वाले समय के साथ एक कार्यक्रम को देखते हुए, हम कुल लागत के एक छोटे से हिस्से के बारे में बात कर रहे हैं।

मुझे लगता है कि आप के साथ जिंदा कोड भ्रमित कर सकते हैं कोड, जो लाइन-दर-लाइन संकलित है। दोनों के बीच एक बहुत महत्वपूर्ण अंतर है।

के रूप में अन्य लोगों ने बताया है, तो आप भी रिलीज़ मोड में इस चलाने के लिए की जरूरत है; डीबग मोड से अधिक अनुकूलन बंद करता है, इसलिए दोनों संस्करण धीमे हो जाएंगे (लेकिन अलग-अलग मात्रा में)।

संपादित - मैं एक दूसरी बात, जो कि इस लाइन का कहना है कि चाहिए:

for (j = 2; j <= Math.Sqrt(i); j++) 

अविश्वसनीय रूप से अक्षम है और बेंच मार्किंग के साथ हस्तक्षेप कर सकते हैं। आपको आंतरिक लूप के के बाहर Math.Sqrt(i)की गणना करनी चाहिए। यह संभव है कि यह दोनों संस्करणों को बराबर राशि से धीमा कर देगा, लेकिन मुझे यकीन नहीं है कि विभिन्न कंपाइलर्स अलग-अलग अनुकूलन करेंगे।

+1

+1। सी ++ अनुकूलन से अधिक पीड़ित है क्योंकि यह प्रदर्शन करने के लिए इनलाइनिंग पर निर्भर करता है। इसके अलावा, जेआईटी डी # पर कुछ अनुकूलन करने जा रहा है भले ही बाइनरी डीबग मोड में बनाया गया हो। –

+2

न केवल यह अधिक अनुकूलन बंद करता है, यह बाहरी त्रुटि जांच का एक गुच्छा जोड़ सकता है। उदाहरण के लिए, विजुअल स्टूडियो डिफ़ॉल्ट डीबग मोड कॉन्फ़िगरेशन में अतिप्रवाह जांच, ढेर जांच, और कई अन्य रोमांचक चीजें जोड़ता है। – kibibu

4

पुन: संयोजित पूर्ण अनुकूलन के साथ सी ++ प्रोग्राम चालू है और परीक्षण को पुनः चलाएं। C# jit कोड को ऑप्टिमाइज़ करेगा जब उसके जब्त किए गए थे ताकि आपने ऑप्टिमाइज्ड सी #/.NET कोड को अप्रत्याशित C++ में तुलना की।

11

आप को रिलीज़ मोड में सी ++ संकलन और प्रदर्शन आप देख रहे हैं परिणाम प्राप्त करने के लिए optimiziations सक्रिय करना होगा।

+0

मैं भी कोशिश करूँगा। – Mack

12

सी ++ में प्रधानमंत्री जनरेटर सही नहीं है

मैं^(1/2) == मैं XOR 0

^बिटवाइज़ XOR ऑपरेटर है और/पूर्णांक प्रभाग है।

1 संपादित, यह सही है, लेकिन ineffecient है: के बाद से मैं 0 == XOR मैं, चलनी sqrt (i) में, लेकिन मैं पर नहीं रुकती।

2 संपादित करें:

sieving थोड़ा और अधिक कुशल किया जा सकता है। (आपको केवल एसक्यूआरटी (एन) की गणना करने की आवश्यकता है)।

void sieve(const int n, unsigned char* primes) 
{ 
     memset(primes, 1, (n+1) * sizeof(unsigned char)); 

     // sieve of eratosthenes 
     primes[0] = primes[1] = 0; 
     int m = floor(sqrt(n)); 
     for (int i = 2; i <= m; i++) 
       if (primes[i]) // no need to remove multiples of i if it is not prime 
         for (int j = i; j <= (n/i); j++) 
           primes[i*j] = 0; 
} 
+0

मैंने इसे सही किया। धन्यवाद। – Mack

+0

मुझे आश्चर्य है कि, हालांकि, यह वास्तव में धीमी गति से चल रहा है या नहीं, क्योंकि सी # संस्करण को वास्तव में प्रत्येक पुनरावृत्ति पर 'Math.Sqrt (i) 'का मूल्यांकन करना है, जो सिंगल-निर्देश XOR से कई गुना अधिक महंगा है, इसलिए यह छोटी गलती वास्तव में सी ++ संस्करण * तेज * कर सकती है क्योंकि कार्यक्रम के दोनों संस्करण अक्षम हैं। – Aaronaught

+2

@Aaronaught: C# संस्करण को छोड़कर Sqrt (i) और C++ संस्करण में लूपिंग है I को लूपिंग है। –

2

पहले, कभी नहीं इस तरह के डिबग मोड में मानक कार्य करें: यह कैसे मैं (इस यद्यपि C99 में है) मेरे अपने उपयोग के लिए एरेटोस्थेनेज की चलनी लागू किया है। सार्थक संख्याएं प्राप्त करने के लिए हमेशा रिलीज मोड का उपयोग करें।

JIT यह, पर चलता है, जबकि precompiled कोड उस पर चल रहा है मंच के लिए करने से इनकी हो सकता है मंच जानने का लाभ दिया है।

+1

शायद, लेकिन वास्तव में उस मंच पर संकलन करने का ओवरहेड है। –

6

यह बहुत अधिक समय ले रहा है क्योंकि एल्गोरिदम गलत है।

for(j = 2; j < (i^(1/2)); j++) 

रूप

for(j = 2; j < (i^0); j++) 

एक ही है मैं sqrt (i) की तुलना में बहुत बड़ा है

for(j = 2; j < i; j++) 

के समान है। केवल चलने वाले समय को देखते हुए, यह परिमाण का बड़ा क्रम है कि यह सी ++ कार्यान्वयन में होना चाहिए।

इसके अलावा, अन्य सभी को जैसे कह रहा है, मुझे नहीं लगता कि यह डिबग मोड में प्रदर्शन परीक्षण करना समझ में आता है है।

+0

मैंने गलती को सही किया है, मुझे खेद है। मैं उन्हें रिलीज मोड में भी चलाने की कोशिश करूंगा। – Mack

0

दोनों परीक्षण अमान्य हैं क्योंकि आपने अनुकूलन के बिना संकलित किया है।

पहले टेस्ट अपने कोड में किसी त्रुटि के कारण, यहां तक ​​कि unoptimized व्यवहार का एक comparrison के रूप में व्यर्थ है; Math.Sqrt(i) i, i^(1/2) का वर्ग रूट देता है I - इसलिए सी ++ सी # से अधिक काम कर रहा है।

आम तौर पर, यह करने के लिए एक उपयोगी चीज नहीं है - आप एक कृत्रिम बेंचमार्क है कि असली दुनिया उपयोग करने के लिए कोई प्रासंगिकता के बराबर है बनाने के लिए कोशिश कर रहे हैं।

2

यह एक मिथक है कि लगातार प्रबंधित कोड में JIT कम्पाइलर मशीन कोड है कि बहुत कम एक C/C++ संकलक द्वारा उत्पन्न एक से कुशल उत्पन्न करता है। प्रबंधित कोड आमतौर पर मेमोरी प्रबंधन और फ़्लोटिंग पॉइंट गणित पर जीतता है, सी/सी ++ आमतौर पर जीतता है जब कोड ऑप्टिमाइज़र कोड अनुकूलित करने में बहुत अधिक समय व्यतीत कर सकता है। आम तौर पर, प्रबंधित कोड लगभग 80% होता है लेकिन यह पूरी तरह से कोड के 10% पर निर्भर करता है जहां एक प्रोग्राम 90% समय व्यतीत करता है।

आपका परीक्षण इस दिखाई नहीं देंगे, आप अनुकूलक सक्षम नहीं किया था और वहाँ अनुकूलन करने के लिए काफी नहीं है।

+0

"प्रबंधित कोड आमतौर पर स्मृति प्रबंधन पर जीतता है" <- क्योंकि सी/सी ++ प्रोग्रामर आम तौर पर आलसी होते हैं और केवल 'std :: vector ' जैसी चीज़ों के बजाय विशाल बफर का उपयोग करते हैं जो कि JIT'd भाषाओं में आम है। संकलित कोड और जेआईटीएड कोड दोनों की गति वही होनी चाहिए, सभी ने कहा और किया, जब तक आप जिटर को स्मृति में लोड करने के लिए समय निकालते हैं (जो जावा के मामले में काफी बड़ा हो सकता है: पी) +1 –

+1

प्रबंधित कोड फ़्लोटिंग पॉइंट ऑपरेशंस पर शायद ही जीत सकता है क्योंकि वर्तमान .NET JIT किसी भी एसएसई निर्देशों को उत्सर्जित नहीं करता है। –

+0

एक से अधिक है, x64 कोई करता है। उदाहरण: http://stackoverflow.com/questions/686483/c-vs-c-big-performance-difference/687741#687741 –

1

लोग, कार्यक्रम की गति को एक दूसरे से तुलना करने से पहले कृपया सीपीयू निर्देश, असेंबली, कैश प्रबंधन इत्यादि पर कई लेख पढ़ने के लिए परेशान हैं और लेखक सिर्फ एक हास्यास्पद मजाकिया दोस्त है। डीबग बिल्ड के प्रदर्शन की जांच करना।

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

0

इस बारे में कैसे:

for(sqrti = 1; sqrti <= 11112; sqrti++) { 
    int nexti = (1+sqrti)*(1+sqrti) 
    for (i = sqrti*sqrti; i < nexti; i++) 
    { 
    int isprime = 1; 
    for(j = 2; j < sqrti; j++) 
     if(!(i%j)) { 
     isprime = 0; 
     break; 
    } 
    } 

} countprimes + = isprime; }

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