了解c ++分配的内存量

Gio*_*Gio 22 c++ memory valgrind memory-management

我正在尝试更好地理解在c ++中分配在堆上的内存量.我写了一个小测试程序,除了填充一些2D矢量之外什么都没做.我在linux 64bit VM上运行它并使用valgrind的massif工具来分析内存.

我正在运行此测试的环境:在Win10上的VirtualBox中运行的Linux VM.VM配置:基本内存:5248MB,4CPU,上限为100%,磁盘类型VDI(动态分配存储).

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我运行以下bash脚本以提取不同值的内存配置文件n(test.o是上面的程序,使用g ++ -std = c ++ 11编译,g ++是版本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
Run Code Online (Sandbox Code Playgroud)

这给了我以下结果:

|--------------------------------|
| 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                |
|--------------------------------|
Run Code Online (Sandbox Code Playgroud)

每个矩阵的大小为n ^ 2,我总共有8个矩阵,因此我预计内存使用量会有所增加f(n) = 8 * n^2.

问题1从n = 250到n = 8000,为什么在n*= 2时内存使用量或多或少乘以4?

从n = 16000到n = 32000,发生了一些非常奇怪的事情,因为valgrind实际上报告了内存减少.

问题2在n = 16000和n = 32000之间发生了什么,堆内存如何可能更少,而理论上应该分配更多的数据?

请参阅下面的massif-visualizer输出,n = 16000和n = 32000.

N = 16000 N = 32000

meo*_*dog 31

1)因为矩阵向量的大小(以及它们的内存占用量)增长为n 2,所以加倍n会导致内存使用量增加四倍.与精确关系的任何偏差(与渐近相反)都是由于不同的因素(例如,使用的元数据,使用的malloc / std::allocator块大小倍增方法vector)

2)你开始耗尽内存,所以Linux是开始一些; 使用--pages-as-heap=yes,如果你想看到的(活性+分页)内存使用情况.(来源:http://valgrind.org/docs/manual/ms-manual.html)

  • 最新的Valgrind 3.13也略微放宽了内存限制.来自http://valgrind.org/docs/manual/dist.news.html:`Valgrind可以使用的内存量从64GB增加到128GB.特别是这意味着在Memcheck上运行时,您的应用程序最多可以分配大约60GB (2认同)