2017-08-21 57 views
21

आवंटित कर रहा है मैं सी ++ में ढेर पर आवंटित स्मृति की मात्रा को बेहतर समझने की कोशिश कर रहा हूं। मैंने एक छोटा परीक्षण कार्यक्रम लिखा है जो मूल रूप से 2 डी वैक्टरों को भरने के अलावा कुछ और नहीं करता है। मैं इसे लिनक्स 64 बिट वीएम पर चला रहा हूं और स्मृति को प्रोफाइल करने के लिए वालग्रींड के मासफ टूल का उपयोग कर रहा हूं।मेमोरी सी ++ की मात्रा को समझना

पर्यावरण मैं इस परीक्षण को चला रहा हूं: लिनक्स वीएम वर्चुअलबॉक्स में Win10 पर चल रहा है। वीएम कॉन्फ़िगरेशन: बेस मेमोरी: 5248 एमबी, 4 सीसीयू, कैप 100%, डिस्क-टाइप वीडीआई (गतिशील रूप से आवंटित स्टोरेज)।

C++ स्मृति रूपरेखा परीक्षण कार्यक्रम:

/** 
* g++ -std=c++11 test.cpp -o test.o 
*/ 

#include <string> 
#include <vector> 
#include <iostream> 

using namespace std; 

int main(int argc, char **arg) { 
    int n = stoi(arg[1]); 
    vector<vector<int> > matrix1(n); 
    vector<vector<int> > matrix2(n); 
    vector<vector<int> > matrix3(n); 
    vector<vector<int> > matrix4(n); 
    vector<vector<int> > matrix5(n); 
    vector<vector<int> > matrix6(n); 
    vector<vector<int> > matrix7(n); 
    vector<vector<int> > matrix8(n); 

    for (int i=0; i<n; ++i) { 
     for (int j=0; j<n; ++j) { 
      matrix1[i].push_back(j); 
     } 
    } 

    for (int i=0; i<n; ++i) { 
     for (int j=0; j<n; ++j) { 
      matrix2[i].push_back(j); 
     } 
    } 

    for (int i=0; i<n; ++i) { 
     for (int j=0; j<n; ++j) { 
      matrix3[i].push_back(j); 
     } 
    } 

    for (int i=0; i<n; ++i) { 
     for (int j=0; j<n; ++j) { 
      matrix4[i].push_back(j); 
     } 
    } 

    for (int i=0; i<n; ++i) { 
     for (int j=0; j<n; ++j) { 
      matrix5[i].push_back(j); 
     } 
    } 

    for (int i=0; i<n; ++i) { 
     for (int j=0; j<n; ++j) { 
      matrix6[i].push_back(j); 
     } 
    } 

    for (int i=0; i<n; ++i) { 
     for (int j=0; j<n; ++j) { 
      matrix7[i].push_back(j); 
     } 
    } 

    for (int i=0; i<n; ++i) { 
     for (int j=0; j<n; ++j) { 
      matrix8[i].push_back(j); 
     } 
    } 
} 

मैं आदेश (test.o कार्यक्रम से ऊपर, के साथ जी ++ -std = c संकलित है n के विभिन्न मूल्यों पर स्मृति प्रोफाइल को निकालने के लिए निम्न बैश स्क्रिप्ट चलाने ++ 11, जी ++ संस्करण 5.3.0) है

valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 250 
valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 500 
valgrind --tool=massif --massif-out-file=massif-n1000.txt ./test.o 1000 
valgrind --tool=massif --massif-out-file=massif-n2000.txt ./test.o 2000 
valgrind --tool=massif --massif-out-file=massif-n4000.txt ./test.o 4000 
valgrind --tool=massif --massif-out-file=massif-n8000.txt ./test.o 8000 
valgrind --tool=massif --massif-out-file=massif-n16000.txt ./test.o 16000 
valgrind --tool=massif --massif-out-file=massif-n32000.txt ./test.o 32000 

यह मैं देता निम्न परिणाम:

|--------------------------------| 
| n  | peak heap memory usage | 
|-------|------------------------| 
| 250 | 2.1 MiB    |   
| 500 | 7.9 MiB    | 
| 1000 | 31.2 MiB    | 
| 2000 | 124.8 MiB    | 
| 4000 | 496.5 MiB    | 
| 8000 | 1.9 GiB    | 
| 16000 | 6.2 GiB    | 
| 32000 | 6.1 GiB    | 
|--------------------------------| 

प्रत्येक मैट्रिक्स आकार में एन^2 होगा, मेरे पास कुल 8 मैट्रिक्स होंगे, इसलिए मुझे उम्मीद है कि मेमोरी उपयोग f(n) = 8 * n^2 के आसपास होगा।

प्रश्न 1 एन = 250 से एन = 8000 तक, मेमोरी उपयोग एन * = 2 पर 4 से अधिक या कम गुणा क्यों किया जाता है?

एन = 16000 से एन = 32000 कुछ बहुत अजीब हो रहा है क्योंकि वालग वास्तव में स्मृति की कमी की रिपोर्ट करता है।

प्रश्न 2 क्या = 16000 और एन = 32000 n के बीच हो रहा है, यह कैसे संभव हो सकता है कि ढेर स्मृति कम है, जबकि सिद्धांत में और अधिक डेटा आवंटित किया जाना चाहिए है?

एन = 16000 और एन = 32000 के लिए मासफ-विज़ुअलाइज़र आउटपुट के नीचे देखें।

n=16000 n=32000

+1

मैं [अपने परिणाम साजिश रची] है (http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiI4KnheMi8zMDAwMDAiLCJjb2xvciI6IiMyQjI0RkYifSx7InR5cGUiOjMsImVxIjpbWyIyNTAiLCIyLjEiXSxbIjUwMCIsIjcuOSJdLFsiMTAwMCIsIjMxLjIiXSxbIjIwMDAiLCIxMjQuOCJdLFsiNDAwMCIsIjQ5Ni41Il0sWyI4MDAwIiwiMTkwMCJdLFsiMTYwMDAiLCI2MjAwIl0sWyIzMjAwMCIsIjYxMDAiXV0sImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIjAiLCIzMjAwMCIsIjAiLCI4MDAwIl19XQ--) – YSC

+5

मैं संकलक और मंच पर आप अपने परीक्षण कर रहे हैं के साथ इस सवाल टैगिंग की सिफारिश करेंगे।स्मृति आवंटन की आंतरिक तंत्र आपके कार्यान्वयन द्वारा निर्धारित की जाती है, सी ++ विषय पर कुछ लगाव करता है। –

+0

मेरी समझ यह है कि कैसे 'वेक्टर' इसकी स्मृति का प्रबंधन करता है कुछ हद तक संकलक पर निर्भर करता है। आम तौर पर 'वेक्टर' के मेमोरी प्रबंधन में मेमोरी के पूर्व आवंटन के साथ-साथ मेमोरी आवंटन के लिए भविष्यवाणी की कुछ डिग्री शामिल होती है। https://frogatto.com/2009/11/17/how-cs-vector-works-the-gritty-details/ –

उत्तर

29

1) क्योंकि आपके मैट्रिक्स वैक्टर के आकार (और इस प्रकार उनके स्मृति पदचिह्न) n के रूप में, हो जाना इतना n दोहरीकरण स्मृति के उपयोग की quadrupling की ओर जाता है। सटीक संबंध (के रूप में asymptotic के खिलाफ) से कोई विचलन विभिन्न कारकों की वजह से कर रहे हैं (उदाहरण के लिए मेटाडाटा malloc/std::allocator द्वारा इस्तेमाल किया, ब्लॉक आकार दोगुना विधि vector द्वारा प्रयोग किया जाता)

2) आप स्मृति से बाहर चलाने के लिए शुरुआत कर रहे हैं , इसलिए लिनक्स पृष्ठ से शुरू हो रहा है; कुल (सक्रिय + पेज्ड) मेमोरी उपयोग देखना चाहते हैं तो --pages-as-heap=yes का उपयोग करें। (स्रोत: http://valgrind.org/docs/manual/ms-manual.html)

+0

मैंने विकल्प के साथ n = 16000 पर अपना परीक्षण चलाने की कोशिश की है - पेज-as-heap = yes, दुर्भाग्य से यह दुर्घटनाग्रस्त होने के लिए valgrind का कारण बनता है। यह बड़ी संख्या में "ब्रैक सेगमेंट ओवरफ्लो थ्रेड # 1 में शुरू होता है, 0x4a2c000 तक नहीं बढ़ सकता" त्रुटियां, जब तक कि अंततः स्मृति और क्रैश से बाहर नहीं हो जाता है। – Gio

+1

@Gio शायद [यह पोस्ट] (https://stackoverflow.com/questions/35129135/valgrind-reporting-a-segment-overflow) आपकी मदद करेगा – meowgoesthedog

+2

इसके अलावा नवीनतम Valgrind, 3.13, ने स्मृति सीमाओं को कुछ हद तक आराम दिया है। Http://valgrind.org/docs/manual/dist.news.html से: 'वॉलग्रिंड का उपयोग करने वाली स्मृति की मात्रा 64 जीबी से बढ़कर 128 जीबी हो गई है। विशेष रूप से इसका मतलब है कि आपका एप्लिकेशन Memcheck पर चलते समय 60GB तक आवंटित कर सकता है। –

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