2010-02-17 17 views
5

मेरे पास एक बहुत बड़ा बहुआयामी वेक्टर है जो हर समय आकार में बदलता है। क्या vector.reserve() फ़ंक्शन का उपयोग करने के लिए कोई बिंदु है जब मुझे केवल आकारों का अच्छा अनुमान पता है।वेक्टर रिजर्व सी ++

तो बुनियादी तौर पर मैं एक वेक्टर

A[256*256][x][y]

जहां एक्स 0 से 50 के कार्यक्रम में हर यात्रा के लिए वापस 0 करने के लिए फिर से चला जाता है और उसके बाद की है। Y मान हर बार भिन्न हो सकते हैं, जिसका अर्थ है कि प्रत्येक [256*256][y] तत्वों के लिए वेक्टर वाई एक अलग आकार का हो सकता है लेकिन 256 से भी छोटा हो सकता है;

तो मेरी समस्या स्पष्ट करने के लिए इस मैं क्या है:

vector<vector<vector<int>>> A; 
for(int i =0;i<256*256;i++){ 
    A.push_back(vector<vector<int>>()); 
    A[i].push_back(vector<int>()); 
    A[i][0].push_back(SOME_VALUE); 
} 

वेक्टर के तत्वों को शामिल करें ...

A.clear(); 

और इस के बाद मैं ऊपर से फिर से एक ही बात करते हैं।

मैं और कैसे वैक्टरों के लिए स्थान आरक्षित करना चाहिए। यदि मैं इसे सही ढंग से समझ गया हूं तो मैं बहुत समय बचाऊंगा यदि मैं रिजर्व का उपयोग करता हूं क्योंकि मैं हर समय आकार बदलता हूं?

कुछ मामलों में मेरे वेक्टर के अधिकतम आकार को आरक्षित करने के नकारात्मक/सकारात्मक पक्ष क्या होंगे जो कुछ मामलों में [256*256][50][256] होगा।

बीटीडब्ल्यू। मैं अलग मैट्रिक्स टेम्पलेट्स और बूस्ट के बारे में पता है, लेकिन इस पर वैक्टर के साथ जाने का फैसला किया है ...

संपादित करें: मैं भी कैसे बहुआयामी सरणियों में आरक्षित समारोह का उपयोग करने के सोच रहा था। यदि मैं केवल दो आयामों में वेक्टर को आरक्षित करता हूं तो क्या यह पूरी चीज की प्रतिलिपि करेगा यदि मैं तीसरी आयाम में अपनी क्षमता को पार करता हूं?

+2

256 * 256 * 50 * 256 * 4 == 3.5 जीबी। क्या यह वाकई सही है? – Will

+0

मुझे डर है कि यह है! लेकिन यह अधिकतम आकार है ... शायद यह 256 * 256 * 50 * 100 की तरह कुछ होगा; तकनीकी रूप से अधिकतम मूल्य कभी पूरा नहीं होगा ... –

उत्तर

4

मदद करने के लिए पर नहीं, औसत स्मृति की खपत को देखो चर्चा के साथ आप निम्नलिखित typedefs पर विचार कर सकते हैं:

typedef std::vector<int> int_t; // internal vector 
typedef std::vector<int_t> mid_t; // intermediate 
typedef std::vector<mid_t> ext_t; // external 

बढ़ रही है (वेक्टर क्षमता में वृद्धि) की लागत int_t केवल इस विशेष वेक्टर की सामग्री को प्रभावित करेगा और किसी भी अन्य तत्व को प्रभावित नहीं करेगा। mid_t बढ़ने की लागत उस वेक्टर में सभी संग्रहीत तत्वों की प्रतिलिपि बनाने की आवश्यकता है, जिसके लिए इसे int_t वेक्टर की आवश्यकता होगी, जो कि अधिक महंगा है। ext_t बढ़ने की लागत बहुत बड़ी है: इसे सभी को पहले से ही कंटेनर में संग्रहीत तत्वों की प्रतिलिपि बनाने की आवश्यकता होगी।

अब प्रदर्शन बढ़ाने के लिए, सही ext_t आकार प्राप्त करने के लिए यह और अधिक महत्वपूर्ण होगा (यह आपके प्रश्न में 256 * 256 तय है)। फिर इंटरमीडिएट mid_t आकार सही करें ताकि महंगा पुनर्विक्रय दुर्लभ हो।

आप जिस स्मृति की बात कर रहे हैं उसकी मात्रा बहुत बड़ी है, इसलिए आप अपनी समस्या को हल करने के लिए कम मानक तरीकों पर विचार करना चाहेंगे। दिमाग में आने वाली पहली चीज़ जोड़ना और संकेत के अतिरिक्त स्तर को जोड़ना है। यदि वास्तविक वैक्टर रखने के बजाय आप वैक्टर में स्मार्ट पॉइंटर्स रखते हैं तो आप mid_t और ext_t वैक्टर (यदि ext_t आकार तय किया गया है, तो mid_t के वेक्टर का उपयोग करें) की लागत को कम कर सकते हैं। अब, यह इंगित करेगा कि आपके डेटा संरचना का उपयोग करने वाला कोड अधिक जटिल होगा (या बेहतर एक रैपर जोड़ें जो संकेतों का ख्याल रखता है)। प्रत्येक int_t वेक्टर स्मृति में एक बार आवंटित किए जाएंगे और mid_t या ext_t पुनर्वितरण में कभी भी स्थानांतरित नहीं होंगे। mid_t को आवंटित करने की लागत आवंटित पूर्णांक की वास्तविक संख्या नहीं, आवंटित int_t वैक्टरों की संख्या के समान है।

using std::tr1::shared_ptr; // or boost::shared_ptr 
typedef std::vector<int> int_t; 
typedef std::vector< shared_ptr<int_t> > mid_t; 
typedef std::vector< shared_ptr<mid_t> > ext_t; 

एक और बात है कि आप ध्यान में रखना चाहिए std::vector::clear() वेक्टर में आवंटित आंतरिक स्थान खाली नहीं है कि, केवल निहित वस्तुओं को नष्ट कर देता है और 0. है कि करने के लिए आकार सेट, clear() बुला स्मृति जारी कभी नहीं होगा । वास्तव में वेक्टर में आवंटित स्मृति को जारी करने के लिए पैटर्न है:

typedef std::vector<...> myvector_type; 
myvector_type myvector; 
... 
myvector.swap(myvector_type()); // swap with a default constructed vector 
+1

वाह, बहुत बहुत धन्यवाद। क्या एक महान जवाब है! 10,000! –

+1

@ डेविड - क्या आप वाकई पहले स्निपेट में 'internal_t' और' intermediate_t' बिट्स प्राप्त कर चुके हैं? – Manuel

+0

@ मैनुअल: नहीं :) मैंने टाइपपीफ को सही किया है –

0

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

एक उदाहरण

के लिए how-do-i-work-with-dynamic-multi-dimensional-arrays-in-c देखें आप एक ही आवंटन हर बार, realloc के रूप में आवश्यक ing और अंत में यह उपयोग के उच्च ज्वार निशान पर रखने का फिर से उपयोग कर सकते हैं।

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

+2

ऐसा मत करो। वैक्टर आपके लिए पुनर्वसन को संभालते हैं। एक सी ++ प्रोग्राम में realloc() का उपयोग लगभग गलत काम होने के लिए निश्चित है। –

+0

इस विशेष उदाहरण में, पीओडी के वैक्टरों के वैक्टरों के वेक्टर, कैसे malloc/realloc/free अनुचित हो सकता है? – Will

+0

कम से कम मेरे पास "तीसरे" आयाम में अलग-अलग आकार हैं, इसलिए यदि मैं वेक्टर का उपयोग करता हूं तो मैं आसानी से आकार तक पहुंच सकता हूं ... –

2

जब भी आप एक और वेक्टर में एक वेक्टर धक्का, आकार सेट धक्का दिया वैक्टर निर्माता में:

A.push_back(vector<vector<int>>(somesize)); 
+0

धन्यवाद! मुझे नहीं पता था कि कोई ऐसा कर सकता है ... –

+1

टेम्पलेट्स में ">>" हमेशा ठीक से संभाला नहीं जाता है। पोर्टेबल बनाने के लिए जगह डालें। बस घबराहट –

0

आप निर्माण समय में एक वेक्टर के आकार पता है, c'tor को आकार गुजरती हैं और push_back के बजाय operator[] का उपयोग करके असाइन करें। यदि आप अंतिम आकार के बारे में पूरी तरह से सुनिश्चित नहीं हैं, तो अनुमान लगाएं (शायद थोड़ा और जोड़ें) औरका उपयोग वेक्टर आरक्षित पर्याप्त मेमोरी अपफ्रंट करने के लिए करें।

कुछ मामलों में मेरे वेक्टर के अधिकतम आकार को सुरक्षित रखने के नकारात्मक/सकारात्मक पक्ष क्या होंगे [256 * 256] [50] [256]।

नकारात्मक पक्ष: स्मृति की संभावित अपशिष्ट। सकारात्मक पक्ष: कम CPU समय, कम ढेर विखंडन। यह एक मेमोरी/सीपीयू ट्रेडऑफ है, इष्टतम विकल्प आपके आवेदन पर निर्भर करता है। यदि आप स्मृति-बाध्य नहीं हैं (अधिकांश उपभोक्ता मशीनों पर पर्याप्त रैम से अधिक है), तो पहले से आरक्षित करने पर विचार करें।

आरक्षित करने के लिए कितनी स्मृति का फैसला करने के लिए, शिखर (आरक्षित 256 * 256 * 50 * 256 एक अच्छा विचार है, जब तक इस तरह के आयाम नियमित रूप से की जरूरत है नहीं है)

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