2017-08-21 51 views
21

Tôi đang cố gắng phát triển sự hiểu biết tốt hơn về lượng bộ nhớ được cấp phát trên heap trong C++. Tôi đã viết một chương trình thử nghiệm nhỏ mà về cơ bản không làm gì khác ngoài việc điền vào một số vectơ 2D. Tôi đang chạy này trên một máy ảo Linux 64bit và sử dụng công cụ massif của valgrind để cấu hình bộ nhớ.Hiểu số lượng bộ nhớ C++ đang phân bổ

Môi trường tôi đang chạy thử nghiệm này trên: Linux VM đang chạy trong VirtualBox trên Win10. Cấu hình VM: Bộ nhớ cơ sở: 5248MB, 4CPU, nắp Ở mức 100%, VDI dạng đĩa (bộ nhớ được định vị động).

C++ bộ nhớ chương trình profiling test:

/** 
* 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); 
     } 
    } 
} 

tôi chạy kịch bản bash sau để giải nén hồ sơ bộ nhớ ở giá trị khác nhau của n (test.o là chương trình trên, biên soạn với g ++ -std = C++ 11, g ++ là phiên bản 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ày mang lại cho tôi kết quả như sau:

|--------------------------------| 
| 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    | 
|--------------------------------| 

Mỗi ma trận sẽ có kích thước n^2, tôi có tổng cộng 8 ma trận, do đó tôi dự kiến ​​sử dụng bộ nhớ là khoảng f(n) = 8 * n^2.

Câu hỏi 1 Từ n = 250 đến n = 8000, tại sao mức sử dụng bộ nhớ nhiều hay ít nhân với 4 ở n * = 2?

Từ n = 16000 đến n = 32000 điều gì đó rất lạ đang xảy ra vì valgrind thực sự báo cáo giảm bộ nhớ.

Câu hỏi 2 Điều gì đang xảy ra giữa n = 16000 và n = 32000, làm sao bộ nhớ heap có thể thấp hơn, trong khi lý thuyết có nhiều dữ liệu hơn nên được phân bổ?

Xem bên dưới đầu ra hình ảnh khối lượng cho n = 16000 và n = 32000.

n=16000 n=32000

+1

Tôi đã [âm mưu kết quả của bạn] (http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiI4KnheMi8zMDAwMDAiLCJjb2xvciI6IiMyQjI0RkYifSx7InR5cGUiOjMsImVxIjpbWyIyNTAiLCIyLjEiXSxbIjUwMCIsIjcuOSJdLFsiMTAwMCIsIjMxLjIiXSxbIjIwMDAiLCIxMjQuOCJdLFsiNDAwMCIsIjQ5Ni41Il0sWyI4MDAwIiwiMTkwMCJdLFsiMTYwMDAiLCI2MjAwIl0sWyIzMjAwMCIsIjYxMDAiXV0sImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIjAiLCIzMjAwMCIsIjAiLCI4MDAwIl19XQ--) – YSC

+5

Tôi muốn giới thiệu gắn thẻ câu hỏi này với trình biên dịch và nền tảng mà bạn đang chạy thử nghiệm của bạn trên.Các cơ chế nội bộ của cấp phát bộ nhớ được xác định bởi việc thực hiện của bạn, C++ làm cho ít áp đặt về chủ đề này. –

+0

Sự hiểu biết của tôi là cách 'vector' quản lý bộ nhớ của nó phụ thuộc vào trình biên dịch ở một mức độ nào đó. Thông thường, việc quản lý bộ nhớ của 'vectơ' bao gồm một số mức độ phân bổ bộ nhớ trước cũng như mức độ dự đoán cho việc cấp phát bộ nhớ. hãy xem https://frogatto.com/2009/11/17/how-cs-vector-works-the-gritty-details/ –

Trả lời

29

1) Bởi vì các kích thước của vector ma trận của bạn (và do đó bộ nhớ của họ) phát triển như n , vì vậy tăng gấp đôi n dẫn đến quadrupling của việc sử dụng bộ nhớ. Bất kỳ độ lệch từ chính xác mối quan hệ (như trái ngược với tiệm cận) là do các yếu tố khác nhau (ví dụ như siêu dữ liệu được sử dụng bởi malloc/std::allocator, phương pháp khối kích thước gấp đôi được sử dụng bởi vector)

2) Bạn đang bắt đầu chạy ra khỏi bộ nhớ , vì vậy Linux đang bắt đầu trang một số; sử dụng --pages-as-heap=yes nếu bạn muốn xem tổng số tổng số (hoạt động + phân trang) sử dụng bộ nhớ. (Nguồn: http://valgrind.org/docs/manual/ms-manual.html)

+0

Tôi đã cố gắng chạy thử nghiệm của mình tại n = 16000 với tùy chọn --pages-as-heap = yes, Thật không may điều này gây ra valgrind sụp đổ. Nó bắt đầu với một số lượng lớn "tràn phân đoạn brk trong thread # 1, không thể phát triển đến 0x4a2c000" lỗi, cho đến khi valgrind cuối cùng hết bộ nhớ và bị treo. – Gio

+1

@Gio có thể [bài đăng này] (https://stackoverflow.com/questions/35129135/valgrind-reporting-a-segment-overflow) sẽ giúp bạn – meowgoesthedog

+2

Đồng thời, phiên bản mới nhất của Valgrind, 3.13, đã làm giảm bớt phần giới hạn bộ nhớ. Từ http://valgrind.org/docs/manual/dist.news.html: 'Dung lượng bộ nhớ mà Valgrind có thể sử dụng đã tăng từ 64GB lên 128GB. Đặc biệt, điều này có nghĩa là ứng dụng của bạn có thể phân bổ tối đa khoảng 60GB khi chạy trên Memcheck.' –

Các vấn đề liên quan