了解 c++ 正在分配的内存量

Understanding the amount of memory c++ is allocating

我正在尝试更好地理解在 C++ 中堆上分配的内存量。我写了一个小的测试程序,它基本上除了填充一些二维向量之外什么都不做。我在 linux 64 位 VM 上 运行ning 并使用 valgrind 的 massif 工具来分析内存。

我运行进行此测试的环境:Linux VM 运行在 Win10 上的 VirtualBox 中进行。 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);
        }
    }
}

我 运行 下面的 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

这给了我以下结果:

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

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

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

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

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

请参见下方 n=16000 和 n=32000 的 massif-visualizer 输出。

1) 因为矩阵向量的大小(以及它们的内存占用)随着 n2 增长,所以将 n 加倍会导致内存使用量增加四倍。与 exact 关系(与 asymptotic 相反)的任何偏差都是由于不同的因素(例如 [=10= 使用的元数据]、块大小vector)

使用的加倍方法

2) 你开始 运行 内存不足,所以 Linux 开始 page 一些;如果您想查看(活动+分页)内存使用情况,请使用--pages-as-heap=yes。 (来源:http://valgrind.org/docs/manual/ms-manual.html