2016-07-20 5 views
6

मैं std::deque का उपयोग कर रहा हूं। मुझे यकीन था कि push_back के साथ एक insert के साथ एक लूप को प्रतिस्थापित करने से प्रदर्शन में वृद्धि होगी। उदाहरण के लिए here भी इसकी अनुशंसा की जाती है।पुश_बैक डालने से तेज़ी से?

लेकिन अब मैं अब और नहीं तो यकीन नहीं है।

मैं परीक्षण कोड पर कुछ मानक दौड़े हैं।

main.cpp:

#include"queueInsert.h" 

#include<Windows.h> 

std::deque<int> queue; 

constexpr size_t len = 64; 

int arr[len]; 

int main() 
{ 
    DWORD startTime = GetTickCount(); 
    for (int i = 0; i < 100000; ++i) 
    { 
     insert(queue, arr, len); 
    } 
    DWORD endTime = GetTickCount(); 

    return endTime - startTime; 
} 

queueInsert.h:

#include<deque> 

void insert(std::deque<int>&, int* arr, int n); 

queueInsert.cpp -push संस्करण

#include "queueInsert.h" 

void insert(std::deque<int>& queue, int* arr, int n) 
{ 
    for (int i = 0; i < n; ++i) 
    { 
     queue.push_back(arr[i]); 
    } 
} 

queueInsert.cpp -insert संस्करण

#include "queueInsert.h" 

void insert(std::deque<int>& queue, int* arr, int n) 
{ 
    queue.insert(queue.end(), arr, arr + n); 
} 

मैं push_back साथ 203 मिलीसेकेंड, लेकिन insert साथ 218 मिलता है। push के लिए 219 मिलों और insert के लिए 266:

6 को बदलने len, और एक लाख के लिए पुनरावृत्तियों में वृद्धि, एक ही परिणाम रहता है। insert के लिए 1437 के खिलाफ push के लिए 1531:

केवल len = 640 साथ push बाहर खो करता है, और फिर भी बहुत कम है।

मैं Windows के तहत VisualStudio 2015 में रिलीज में संकलन कर रहा हूँ 10

मुझे यकीन है कि संकलक पुनरावृत्तियों की लगातार संख्या इनलाइन करने या छोरों fusing के रूप में अनुकूलन नहीं कर रहा है कर रहा हूँ, हर बार के रूप में मैं बदल कार्यान्वयन केवल queueInsert.cpp पुन: संकलित किया गया है।

मैं रूपरेखा गलत कर रहा हूं? या क्या मुझे वास्तव में push_back रखना चाहिए यदि तत्वों को डालने की मात्रा बड़ी होने की संभावना नहीं है? सामान्य डालने, सामने डालें, पीठ में सम्मिलित करें:

+0

* मुझे यकीन है कि संकलक अनुकूलन नहीं कर रहा है * - चलिए असेंबली लिस्टिंग देखें। – PaulMcKenzie

+1

मैंने मूल आलेख पढ़ा, – Slava

+0

कभी नहीं, मेरा मतलब है वेक्टर तत्वों के अनुक्रम के रूप में, 'std :: vector' नहीं। मैंने अर्थ स्पष्ट करने के लिए सही किया है। –

उत्तर

11

deque::insert प्रभावी ढंग से संचालन के 3 संभव तरीके है। इसके कारण, हर बार जब आप insert पर कॉल करते हैं, तो यह जांचने के लिए एक परीक्षण करना होगा कि इसे किस तरह से सम्मिलित करने की आवश्यकता है। तो इसे आगे और पीछे के खिलाफ गुजरने वाले इटरेटर का परीक्षण करना होगा। पीठ में सम्मिलित करें:

deque::push_back आपरेशन का केवल 1 मोड है।

थोक सम्मिलन ऑपरेशन का उपयोग करने का लाभ यह है कि कंटेनर पूरी तरह से सम्मिलन करने के लिए आवंटित करने के लिए कितनी मेमोरी की आवश्यकता है, क्योंकि यह इटरेटर रेंज की लंबाई प्राप्त कर सकता है। तो थोक डालने जितना बड़ा होगा, बेहतर insert होगा।

ठीक है, कम से कम vector के लिए बेहतर।

vector के साथ देखें, यदि आप एक समय में 30,000 तत्व डालते हैं, तो आप ~ 14-15 बार पुन: आवंटन करने की संभावना रखते हैं। इसका मतलब है कि नई मेमोरी आवंटित करना और पुराने डेटा को उस स्मृति में कॉपी करना। जबकि यदि आप एक बार में 30,000 तत्व डालते हैं, तो आपको एकल पुनर्वितरण मिलता है।

deque आमतौर पर निश्चित आकार के ब्लॉक की एक सरणी के रूप में लागू किया जाता है। इसके कारण, यदि आप एक समय में 30,000 तत्व डालते हैं, तो आपको ~ 3,000 आवंटन मिलेगा (ब्लॉक आकार के आधार पर)। यदि आप एक बार में 30,000 तत्वों को सम्मिलित करते हैं, तो आपको ... ~ 3,000 आवंटन मिलेगा। तो आप वास्तव में ज्यादा बचत नहीं कर रहे हैं।

चूंकि थोक डालने deque के लिए एकल डालने से बहुत अलग नहीं है, माइक्रो-ऑप्टिमाइज़ेशन समस्याओं के बीच एक लड़ाई क्या होती है। प्रत्येक insert कॉल को उस प्रविष्टि को निष्पादित करने के तरीके को देखने के लिए इटेटरेटर तुलना करना है। इस प्रकार, सम्मिलन छोटे, कम कुशल insert होगा। push_back में उस ओवरहेड नहीं है, लेकिन यह प्रत्येक तत्व के लिए एक फ़ंक्शन कॉल है। तो यह उस उपर है।

इसलिए, insert संभावित रूप से जीत जाएगा जब प्रति सम्मिलित तत्वों की संख्या अधिक होगी।

+0

मैंने इसके बारे में सोचा, लेकिन निष्कर्ष निकाला कि यह महत्वपूर्ण नहीं हो सकता है, जो कि '64' तत्वों पर एक ही जांच है। हालांकि, मैं मानता हूं कि इस समय यह सबसे संभावित स्पष्टीकरण है। –

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