2013-06-04 13 views
8

मैं वर्तमान में स्मृति की 2.5GB के लायक के बारे में बहुत बड़े डेटा सेट के साथ काम कर रहा हूँ ..std :: वेक्टर स्वैप मेमोरी विखंडन का कारण बनता है?

मैं वर्तमान में कक्षा डाटा का एक वेक्टर कि 1) मेटा डेटा 2) boost::ptr_list<MemoryBlock>

शामिल का उपयोग करके इस भंडारण कर रहा हूँ MemoryBlock वर्ग 1) मेटा डाटा 2) std::vector<XYZ>

जब पॉप्युलेट, मैं 50,000 के समूह में मेरी std::vector<xyz> आरक्षित हैं। यदि मेरे वेक्टर के स्थानिक आयाम बड़े हो जाते हैं, तो मैं एक नया मेमोरीब्लॉक बनाउंगा और वेक्टर को उचित आकार में कम करने के लिए std::vector<XYZ>(Points).swap(Points) का उपयोग करूंगा।

अब समस्या ... ऐसा लगता है जब मैं स्वैप चाल का उपयोग अपने सरणी आकार बदलने के लिए, मैं सेट एक नया डेटा में अपने डेटा और लोड हो रहा है के सभी साफ करने के बाद std :: bad_alloc अपवादों में चलाने के लिए शुरू कि।

डेटा की मात्रा है कि मैं में लोड कर सकते हैं तेजी से सिकुड़ता है ... यह तो हर बार जब मैं सेट ... एक नया डेटा में अपने डेटा और लोड स्पष्ट करने के लिए उदाहरण के लिए, मेरे प्रारंभिक डेटा सेट में लोड होगा जारी रहेगा 100000000 मूल्यों

अगली बार 70,000,000 मूल्यों

अगली बार 50,000,000 मूल्यों

अगली बार लोड होगा 20,000,000 मूल्यों आदि ...

मेरी पहली सोचा एक स्मृति रिसाव है, लेकिन वहां कुछ भी नहीं है जिसे मैं पहचानने में सक्षम हूं। स्वैप को छोड़कर कोड में हर चीज का उपयोग किसी भी समस्या के साथ बहुत लंबे समय तक बड़े पैमाने पर किया जाता है।

यदि मैं स्वैप/स्थानिक आयाम जांच का उपयोग नहीं करता, तो सब कुछ जारी रहता है और ठीक से काम करता है।

कोई विचार?!

संपादित

bool Check_MemBlock_Size(MemoryBlock &CurrMemblock, XYZ CheckPoint){ 

    // Set a minimum of 5000 points in each memory block regardless of physical size.. 
    if(CurrMemblock.PointsArr.size() > 5000){ 
     XYZ TestMin, TestMax; 
     TestMin = CurrMemblock.Min; 
     TestMax = CurrMemblock.Max; 

     // Check what the bounding box would be if we included the check point.. 
     if(TestMax.x < CheckPoint.x) 
      TestMax.x = CheckPoint.x; 
     if(TestMax.y < CheckPoint.y) 
      TestMax.y = CheckPoint.y; 
     if(TestMax.z < CheckPoint.z) 
      TestMax.z = CheckPoint.z; 

     if(TestMin.x > CheckPoint.x) 
      TestMin.x = CheckPoint.x; 
     if(TestMin.y > CheckPoint.y) 
      TestMin.y = CheckPoint.y; 
     if(TestMin.z > CheckPoint.z) 
      TestMin.z = CheckPoint.z; 

     // If the new bounding box is too big, lets break it off. 
     if(fabs(TestMax.x - TestMin.x) > 100 || fabs(TestMax.y - TestMin.y) > 100 || fabs(TestMax.z - TestMin.z) > 50){ 

      std::vector<XYZ>(CurrMemblock.PointsArr).swap(CurrMemblock.PointsArr); 

      return false; 

     } 
    } 


    return true; 
} 

यहाँ इस का उपयोग कर कोड के खंड है ..

    if(Check_MemBlock_Size(*MemBlock, NewPoint) == false){ 

         Data->MemoryBlocks.push_back(MemBlock); 

         try { 
          MemBlock = new MemoryBlock(); 
         } catch (std::bad_alloc) { 
          printf("Not enough memory\n"); 
          delete Buffer; 
          break; 
         } 

         BlockSize = 0; 

         try{ 
          MemBlock->PointsArr.reserve(MaxBlockSize); 
         } catch(std::bad_alloc){ 
          delete MemBlock; 
          delete Buffer; 
          printf("Not enough memory\n"); 
          break; 
         } 

        } 


        // Push the point to our current memory block 
        BlockSize++; 
        MemBlock->PointsArr.push_back(NewPoint); 

        .... // More stuff going on here.. irrelevant 

        // push a new memory block if we hit the block point limit. 
        if(BlockSize >= MaxBlockSize){ 

         Data->MemoryBlocks.push_back(MemBlock); 

         try { 
          MemBlock = new MemoryBlock(); 
         } catch (std::bad_alloc) { 
          printf("Not enough memory\n"); 
          delete Buffer; 
          break; 
         } 

         BlockSize = 0; 

         try{ 
          MemBlock->PointsArr.reserve(MaxBlockSize); 
         } catch(std::bad_alloc){ 
          printf("Not enough memory\n"); 
          delete MemBlock; 
          delete Buffer; 
          break; 
         } 

        } 
+3

प्रत्येक स्मृति आवंटन में स्मृति विखंडन का कारण बनने की क्षमता है। – PlasmaHH

+1

मुझे लगता है कि सी ++ 11 वेक्टर :: shrink_to_fit और रचनाकारों को स्थानांतरित करें (बढ़ते समय प्रतिलिपि बनाने के बजाय) आपकी समस्याओं को कम कर सकते हैं। विकल्प पर सी ++ 11 है? – mirk

+0

सी ++ 11 एक विकल्प नहीं है। मैं समझता हूं कि प्रत्येक आवंटन कुछ विखंडन का कारण बन सकता है, लेकिन जिस डिग्री को मैं देख रहा हूं वह नहीं। – user1000247

उत्तर

6

इस तकनीक को विखंडन की गारंटी करने के अगर बीच में कॉल करने के लिए Check_MemBlock_Size() आप कुछ और गतिशील आवंटन कर रहा है । इसका कारण यह है कि आप अपने छोटे हिस्सा आवंटन, स्मृति में एक 50K वस्तु छेद है, जो अब आंशिक रूप से कुछ और स्मृति द्वारा भरा जा सकता बनाने के बाद अपने 50K आवंटन जारी है, जो अपने अगले अपने MemoryBlock उपयोग नहीं कर सकते के पुनर्निर्माण।

आप एक वैश्विक वेक्टर के बजाय एक अस्थायी एक इस 50K वस्तु आवंटन धारण करने के लिए बना सकते हैं। तब, जब आप अगले एक नया MemoryBlock पुनर्निर्माण, बजाय एक नया 50K वस्तु वेक्टर आकार बदलने के लिए, बस वैश्विक एक में स्वैप। जब आप इसे कम करना चाहते हैं, तो फिर से वैश्विक के साथ स्वैप करें। 50 के आरक्षित मेमोरी का पुन: उपयोग करने से इस तरह के किसी भी विखंडन को हटा दिया जाएगा जिससे इस आवंटन में योगदान हो सकता है।

हालांकि, वहाँ अपने कार्यक्रम में विखंडन के अन्य स्रोतों हो सकता है यदि आप सुनिश्चित नहीं लीक कर रहे हैं कर रहे हैं। आम तौर पर, विखंडन गतिशील रूप से आवंटित बड़ी और छोटी वस्तुओं के मिश्रण के कारण होता है, प्रत्येक अलग-अलग जीवनकाल के साथ होता है।इसे हल करने के कई तरीके हैं, लेकिन इसे संभालने का एक तरीका स्मृति के पूल के साथ है। इस अर्थ में एक पूल एक ही आकार और समान जीवनकाल की वस्तुओं का संग्रह है, जो कस्टम आवंटक के भीतर एक साथ समूहित होता है। इस तरह की स्मृति का विलोपन अपने पूल में वापस कर दिया जाता है। अगर स्मृति delete के साथ सिस्टम में कभी वापस नहीं आती है, तो पूल भविष्य में आवंटन को उसी ऑब्जेक्ट प्रकार के लिए पहले आवंटित स्मृति को पुन: उपयोग करने की अनुमति देकर विखंडन का मुकाबला करता है। पूल चोटी रनटाइम उपयोग के लिए बढ़ते हैं, और विखंडन इससे भी बदतर नहीं होता है।

+0

धन्यवाद! ऐसा लगता है जैसे यह काम कर सकता है। मैं इसे – user1000247

+0

का प्रयास करूंगा यह काम नहीं करता है :( – user1000247

+0

@ user1000247: इसका मतलब क्या है? – jxh

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