2009-12-13 12 views
18

यहां एक जिज्ञासा है जिसका मैं जांच कर रहा हूं। एनईटी डिक्शनरी कक्षा एक परीक्षण में एसटीएल unordered_map की तुलना में हास्यास्पद तेजी से प्रदर्शन करता है, और मैं यह नहीं समझ सकता कि क्यों।सी ++ से सी # में तेजी से हैश तालिका?

(0.5 सेकंड बनाम मेरी मशीन पर 4 सेकंड) (.NET 3.5 एसपी 1 बनाम विजुअल स्टूडियो 2008 एक्सप्रेस SP1 के एसटीएल)

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

यह एक साधारण परीक्षण है, भंडारण और पूर्णांकों को पुन: प्राप्त।

सी #:

const int total = (1 << 20); 
int sum = 0; 
Dictionary<int, int> dict = new Dictionary<int, int>(); 
for(int i = 0; i < total; i++) 
{ 
    dict.Add(i, i * 7); 
} 

for(int j = 0; j < (1 << 3); j++) 
{ 
    int i = total; 
    while(i > 0) 
    { 
     i--; 
     sum += dict[i]; 
    } 
} 
Console.WriteLine(sum); 

सी ++:

const int total = (1 << 20); 
int sum = 0; 
std::tr1::unordered_map<int, int> dict; 
for(int i = 0; i < total; i++) 
{ 
    dict.insert(pair<int, int>(i, i * 7)); 
} 

for(int j = 0; j < (1 << 3); j++) 
{ 
    int i = total; 
    while(i > 0) 
    { 
     i--; 
     std::tr1::unordered_map<int, int>::const_iterator found = 
      dict.find(i); 
     sum += found->second; 
    } 
} 
cout << sum << endl; 
+0

सी ++ संस्करण एक शब्दकोश है जैसे आपके द्वारा लिखा गया है? –

+7

मूल मशीन कोड क्या है? आपको क्या लगता है सी # के रूप में चलता है? –

+1

आप प्रदर्शन को कैसे मापते हैं? – stefanB

उत्तर

10

दो संस्करणों, समान नहीं होते हैं अपने अपने सी ++, जबकि पाश में से प्रत्येक के पास में पुनरावर्तक का निर्माण कर रहे हैं। जो CPU समय लेता है और आपके परिणाम फेंकता है। तथ्य यह है अव्यवस्थित नक्शा ले जाता है कि एक जोड़ी ऐसी वस्तु के निर्माण के लिए मजबूर करता है, जब सी # तेजी से जोड़ें में दो पैरामीटर प्रदान करने के साथ हो सकता है:

+0

सहमत - "dict.insert (जोड़ी (i, i * 7)) को बदलने का प्रयास करें;" "dict [i] = i * 7;" एक कम स्तर का गूक। –

+0

वह, और वे C# संस्करण में सरणी ऑपरेटर और C++ संस्करण में find() विधि का उपयोग कर रहे हैं। – Glen

+0

@Glen: "सर ऑपरेटर" एक वाक्य रचनात्मक सुविधा है जो 'FindEntry' विधि को कॉल करती है। इसका कोई गति लाभ नहीं है। –

2

कोड के स्तर पर कुछ मतभेद होगा। हैशिंग समारोह, या जिस तरह से टकराव से निपटने के लिए के कार्यान्वयन, अलग अलग प्रदर्शन पैटर्न का कारण होगा:

एक और मुद्दा खुद को hashtables का कार्यान्वयन है।

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

5

आप स्पष्ट स्मृति प्रबंधन की लागत को मापने रहे हैं। अधिक आंकड़े उपलब्ध here. यह relevant too. है और Chris Sells' attempt नियतात्मक अंतिम रूप दिए जाने को जोड़ने के लिए करने के लिए CLR उल्लेखनीय है कर रहे हैं।

+2

+1 के साथ अच्छे सी # कोड की तुलना नहीं करना चाहिए - महान लिंक के लिए। –

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