2009-10-23 14 views
8

मैं 2 बातें करने की कोशिश की: (छद्म नीचे कोड)वेक्टर सरणी से धीमा शुरू कर रहा है ... क्यों?

int arr[10000]; 
for (int i = 0; i < 10000; i++) 
{ 
    for (int j = 0; j < 10000; j++) 
    { 
     arr[j] = j; 
    } 
} 

और

vector<int> arr(10000); 
for (int i = 0; i < 10000; i++) 
{ 
    for (int j = 0; j < 10000; j++) 
    { 
     arr[j] = j; 
    } 
} 

मैं दोनों कार्यक्रमों भाग गया और "समय" शेल कमांड का उपयोग कर इसे समय समाप्त हुआ। प्रोग्राम 1 सेकंड में चलता है, प्रोग्राम 2 सेकंड में चलता है। मैंने कंपाइलर ऑप्टिमाइज़ेशन के साथ दोनों प्रोग्राम चलाए, और दोनों प्रोग्राम एक ही समय में (0.38 एस) में भाग गए। मैं इन परिणामों से उलझन में हूँ। क्या कोई मुझे बता सकता है कि यह क्यों हो रहा है?

धन्यवाद!

+2

क्या आपका मतलब है कि उन्होंने अनुकूलन * बंद * के साथ 5/30 सेकंड लिया? – jalf

+0

ध्यान रखें कि वे बिल्कुल बराबर नहीं हैं। वेक्टर डिफ़ॉल्ट रूप से ढेर को आवंटित करता है, लेकिन सरणी ढेर पर है। – GManNickG

+0

हाय आधा, हाँ यह मेरे प्रश्न का हिस्सा था। मैं भी अनुकूलन के बाद एक ही समय में निष्पादित करके भ्रमित था। – Aishwar

उत्तर

16

टेम्पलेट के लिए, subscripting [] ऑपरेटर के साथ किया जाता है। ऑप्टिमाइज़ेशन बंद होने के साथ, आमतौर पर एक वास्तविक फ़ंक्शन कॉल के रूप में जेनरेट किया जाएगा, जिसमें किसी सरणी में सबस्क्रिप्टिंग के रूप में सरल कुछ ओवरहेड जोड़ना होगा। जब आप अनुकूलन चालू करते हैं, तो यह उस ओवरहेड को हटाकर, इनलाइन उत्पन्न होता है।

+0

हे जैरी, आपके उत्तर के लिए धन्यवाद। यह अब समझ में आता है। मुझे लगता है कि ऐरे के साथ, [] ऑपरेटर को कॉल नहीं करता है [] क्योंकि यह एक 'प्राकृतिक' (बेहतर शब्द की कमी के लिए) प्रकार है। इसलिए 5/30। – Aishwar

+0

दाएं - एक अंतर्निर्मित सरणी के लिए, सबस्क्रिप्टिंग कोड लगभग निश्चित रूप से * हमेशा * उत्पन्न इनलाइन है। –

+0

और यह अंडरस्कोर करता है कि फ़ंक्शन कॉल ओवरहेड वास्तव में कैसे जोड़ सकता है। – Crashworks

8

डिबगिंग मोड में, std::vector के कार्यान्वयन उपयोग में आसानी के लिए जाँच चलाने के समय का एक बहुत प्रदान करते हैं। यह जांच देशी सरणी के लिए उपलब्ध नहीं है। उदाहरण के लिए, VC2008 में, आप डिबगिंग मोड में अपने vector उदाहरण संकलन करता है, तो, वहाँ operator[] के मामले में range-checkingभी हो जाएगा।

5

अपने गैर अनुकूलित वेक्टर कार्यान्वयन सीमा जाँच प्रदर्शन कर रहा है, तो उस विसंगति के लिए खाते में जाएगा।

+0

++ मेरा अनुमान है कि आप सही हैं, लेकिन मैं उसे ढूंढना चाहता था (या उसे)। –

0

क्योंकि जब आप वेक्टर आगमन (10000) लिखना; आप एक ऑब्जेक्ट बनाते हैं, इसे फ़ंक्शन कहते हैं ... जब आप int arr [10000] बनाते हैं तो यह धीमा हो जाएगा;

0

आपके उदाहरणों में, सरणी ढेर पर है। सरणी में डेटा तक पहुंचने में स्टैक पर डेटा तक पहुंच शामिल है। वह तेज है।

दूसरी ओर, जबकि vector ढेर पर, एक std::vector के लिए डेटा कहीं और आवंटित किया जाता है (डिफ़ॉल्ट रूप से यह std::allocator के माध्यम से ढेर पर आवंटित है)। vector में डेटा तक पहुंचने में ढेर पर डेटा तक पहुंच शामिल है। ढेर पर डेटा तक पहुंचने से यह बहुत धीमी है।

आप प्रदर्शन दंड के लिए कुछ है, हालांकि मिलता है। std::vector बढ़ने योग्य है, जबकि एक नियमित सरणी नहीं है। इसके अलावा, std::vector का आकार स्थिरता संकलित करने की आवश्यकता नहीं है, जबकि स्टैक पर सरणी का आकार होता है। एक ढेर-आवंटित सरणी (operator new[] के माध्यम से) को संकलन-समय स्थिर नहीं होना चाहिए। यदि आप std::vector के साथ एक हीप आवंटित सरणी की तुलना करते हैं तो आप पाएंगे कि प्रदर्शन बहुत करीब है।

int* arr = new int[10000]; 
for (int i = 0; i < 10000; i++) 
{ 
    for (int j = 0; j < 10000; j++) 
    { 
     arr[j] = j; 
    } 
} 

delete[] arr; // std::vector does this for you 
4

ये अच्छे उत्तर हैं, लेकिन आपके लिए एक त्वरित तरीका है जिसे आप ढूंढ सकते हैं।

आप प्रदर्शन में 6-से-1 अंतर देख रहे हैं, है ना? बस धीमी गति से चलाएं और "रोकें" बटन दबाएं। फिर कॉल स्टैक को देखें। संभावना 6 (83%) में से 5 है कि आप देखेंगे कि यह उन 25 अतिरिक्त सेकंडों को कैसे खर्च कर रहा है। जितनी चाहें उतनी अंतर्दृष्टि प्राप्त करने के लिए इसे कई बार करें।

अनुकूलित मामले के लिए, प्रोग्राम 1 के साथ ऐसा ही करें। चूंकि यह अनुकूलित प्रोग्राम की तुलना में 13 गुना धीमा है, इसलिए आप संभावित कारण 12/13 = 92% के साथ प्रत्येक "रोक" पर कारण देखेंगे।

यह this technique का एक आवेदन है।

+1

मैंने पहली बार अच्छी ओले 'पॉज़ तकनीक को देखते हुए कई डेवलपर के दिमाग उड़ाए हैं, खासकर जब वे इसे नहीं खरीदते हैं और एक और सर्किल घंटे बिताते हैं-केवल एक पूर्ण प्रोफाइलिंग रन को "पॉज़" खोजने के लिए पहले से ही इसे खींचा गया है। – DanO

+0

@ डैनो: हाँ। मैं सिर्फ शब्द निकालने की कोशिश कर रहा हूं। लोगों को यह नहीं पता करने का कोई कारण नहीं है। –

+0

हे माइक, उत्तर के लिए धन्यवाद। मैं इसे आजमा देना चाहता हूं, लेकिन मैं अपने कार्यक्रमों को संकलित करने के लिए कमांड लाइन पर्यावरण और जीसीसी का उपयोग कर रहा हूं (मैं इस माहौल में नया हूं)। क्या कोई रास्ता है कि मैं इसे रोक सकता हूं और वहां स्टैक ट्रेस देख सकता हूं? धन्यवाद :) – Aishwar

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